2 * rt5640_ioctl.h -- RT5640 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 "rt56xx_ioctl.h"
15 #include "rt5640_ioctl.h"
17 #if defined(CONFIG_SND_SOC_RT5642_MODULE) || defined(CONFIG_SND_SOC_RT5642)
18 #include "rt5640-dsp.h"
21 static hweq_t hweq_param[] = {
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},
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},
38 #define RT5640_HWEQ_LEN ARRAY_SIZE(hweq_param)
40 int rt5640_update_eqmode(
41 struct snd_soc_codec *codec, int mode)
43 struct rt56xx_ops *ioctl_ops = rt56xx_get_ioctl_ops();
47 if(codec == NULL || mode >= RT5640_HWEQ_LEN)
50 dev_dbg(codec->dev, "%s(): mode=%d\n", __func__, mode);
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]);
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);
72 static void set_drc_agc_enable(struct snd_soc_codec *codec, int enable, int path)
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);
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)
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);
93 static void set_digital_boost_gain(struct snd_soc_codec *codec,
94 int post_gain, int pre_gain)
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);
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)
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);
118 static void set_drc_agc_compression(struct snd_soc_codec *codec,
119 int compression_en, int compression_ratio)
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);
129 static void get_drc_agc_enable(struct snd_soc_codec *codec, int *enable, int *path)
131 unsigned int reg = snd_soc_read(codec, RT5640_DRC_AGC_1);
133 *enable = (reg & RT5640_DRC_AGC_MASK) >> RT5640_DRC_AGC_SFT;
134 *path = (reg & RT5640_DRC_AGC_P_MASK) >> RT5640_DRC_AGC_P_SFT;
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)
140 unsigned int reg = snd_soc_read(codec, RT5640_DRC_AGC_3);
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;
151 static void get_digital_boost_gain(struct snd_soc_codec *codec,
152 int *post_gain, int *pre_gain)
154 unsigned int reg = snd_soc_read(codec, RT5640_DRC_AGC_2);
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;
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)
163 unsigned int reg = snd_soc_read(codec, RT5640_DRC_AGC_3);
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;
176 static void get_drc_agc_compression(struct snd_soc_codec *codec,
177 int *compression_en, int *compression_ratio)
179 unsigned int reg = snd_soc_read(codec, RT5640_DRC_AGC_2);
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;
187 int rt5640_ioctl_common(struct snd_hwdep *hw, struct file *file,
188 unsigned int cmd, unsigned long arg)
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;
197 if (copy_from_user(&rt56xx, _rt56xx, sizeof(rt56xx))) {
198 dev_err(codec->dev,"copy_from_user faild\n");
201 dev_dbg(codec->dev, "%s(): rt56xx.number=%d, cmd=%d\n",
202 __func__, rt56xx.number, cmd);
203 buf = kmalloc(sizeof(*buf) * rt56xx.number, GFP_KERNEL);
206 if (copy_from_user(buf, rt56xx.buf, sizeof(*buf) * rt56xx.number)) {
211 case RT_SET_CODEC_HWEQ_IOCTL:
215 rt5640_update_eqmode(codec, eq_mode);
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))
224 case RT_SET_CODEC_SPK_VOL_IOCTL:
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);
233 case RT_SET_CODEC_MIC_GAIN_IOCTL:
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);
242 case RT_SET_CODEC_3D_SPK_IOCTL:
243 if(rt56xx.number < 4)
245 if (NULL == ioctl_ops->index_update_bits)
250 mask1 |= RT5640_3D_SPK_MASK;
252 mask1 |= RT5640_3D_SPK_M_MASK;
254 mask1 |= RT5640_3D_SPK_CG_MASK;
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);
264 case RT_SET_CODEC_MP3PLUS_IOCTL:
265 if(rt56xx.number < 5)
269 mask1 |= RT5640_M_MP3_MASK;
271 mask1 |= RT5640_EG_MP3_MASK;
273 mask2 |= RT5640_OG_MP3_MASK;
275 mask2 |= RT5640_HG_MP3_MASK;
277 mask2 |= RT5640_MP3_WT_MASK;
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);
287 case RT_SET_CODEC_3D_HEADPHONE_IOCTL:
288 if(rt56xx.number < 4)
290 if (NULL == ioctl_ops->index_update_bits)
295 mask1 |= RT5640_3D_HP_MASK;
297 mask1 |= RT5640_3D_BT_MASK;
299 mask1 |= RT5640_3D_1F_MIX_MASK;
301 mask1 |= RT5640_3D_HP_M_MASK;
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);
309 ioctl_ops->index_update_bits(codec,
310 0x59, 0x1f, *(buf+4));
313 case RT_SET_CODEC_BASS_BACK_IOCTL:
314 if(rt56xx.number < 3)
318 mask1 |= RT5640_BB_MASK;
320 mask1 |= RT5640_BB_CT_MASK;
322 mask1 |= RT5640_G_BB_BST_MASK;
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);
330 case RT_SET_CODEC_DIPOLE_SPK_IOCTL:
331 if(rt56xx.number < 2)
333 if (NULL == ioctl_ops->index_update_bits)
338 mask1 |= RT5640_DP_SPK_MASK;
340 mask1 |= RT5640_DP_ATT_MASK;
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 );
347 case RT_SET_CODEC_DRC_AGC_ENABLE_IOCTL:
348 if(rt56xx.number < 2)
350 set_drc_agc_enable(codec, *(buf), *(buf + 1));
353 case RT_SET_CODEC_DRC_AGC_PAR_IOCTL:
354 if(rt56xx.number < 4)
356 set_drc_agc_parameters(codec, *(buf), *(buf + 1),
357 *(buf + 2), *(buf + 3));
360 case RT_SET_CODEC_DIGI_BOOST_GAIN_IOCTL:
361 if(rt56xx.number < 2)
363 set_digital_boost_gain(codec, *(buf), *(buf + 1));
366 case RT_SET_CODEC_NOISE_GATE_IOCTL:
367 if(rt56xx.number < 4)
369 set_noise_gate(codec, *(buf), *(buf + 1),
370 *(buf + 2), *(buf + 3));
373 case RT_SET_CODEC_DRC_AGC_COMP_IOCTL:
374 if(rt56xx.number < 2)
376 set_drc_agc_compression(codec, *(buf), *(buf + 1));
379 case RT_SET_CODEC_WNR_ENABLE_IOCTL:
380 if (NULL == ioctl_ops->index_update_bits)
383 ioctl_ops->index_update_bits(codec, RT5640_WND_1,
384 RT5640_WND_MASK, *(buf) << RT5640_WND_SFT );
387 case RT_GET_CODEC_DRC_AGC_ENABLE_IOCTL:
388 if(rt56xx.number < 2)
390 get_drc_agc_enable(codec, (buf), (buf + 1));
391 if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
395 case RT_GET_CODEC_DRC_AGC_PAR_IOCTL:
396 if(rt56xx.number < 4)
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))
405 case RT_GET_CODEC_DIGI_BOOST_GAIN_IOCTL:
406 if(rt56xx.number < 2)
408 get_digital_boost_gain(codec, (buf), (buf + 1));
409 if (copy_to_user(rt56xx.buf, buf,
410 sizeof(*buf) * rt56xx.number))
414 case RT_GET_CODEC_NOISE_GATE_IOCTL:
415 if(rt56xx.number < 4)
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))
423 case RT_GET_CODEC_DRC_AGC_COMP_IOCTL:
424 if(rt56xx.number < 2)
426 get_drc_agc_compression(codec, (buf), (buf + 1));
427 if (copy_to_user(rt56xx.buf, buf,
428 sizeof(*buf) * rt56xx.number))
432 case RT_GET_CODEC_SPK_VOL_IOCTL:
433 *buf = (snd_soc_read(codec, RT5640_SPK_VOL) & RT5640_L_VOL_MASK)
435 if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
439 case RT_GET_CODEC_MIC_GAIN_IOCTL:
440 *buf = (snd_soc_read(codec, RT5640_IN1_IN2) & RT5640_BST_MASK1)
442 if (copy_to_user(rt56xx.buf, buf, sizeof(*buf) * rt56xx.number))
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);
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:
468 EXPORT_SYMBOL_GPL(rt5640_ioctl_common);