diff options
-rw-r--r-- | include/sound/soc.h | 21 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 95 |
2 files changed, 116 insertions, 0 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index 697e7ffe39d7..65e9d03ed4f5 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -170,6 +170,21 @@ | |||
170 | .get = xhandler_get, .put = xhandler_put, \ | 170 | .get = xhandler_get, .put = xhandler_put, \ |
171 | .private_value = (unsigned long)&xenum } | 171 | .private_value = (unsigned long)&xenum } |
172 | 172 | ||
173 | #define SOC_DOUBLE_R_SX_TLV(xname, xreg_left, xreg_right, xshift,\ | ||
174 | xmin, xmax, tlv_array) \ | ||
175 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
176 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | ||
177 | SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
178 | .tlv.p = (tlv_array), \ | ||
179 | .info = snd_soc_info_volsw_2r_sx, \ | ||
180 | .get = snd_soc_get_volsw_2r_sx, \ | ||
181 | .put = snd_soc_put_volsw_2r_sx, \ | ||
182 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | ||
183 | {.reg = xreg_left, \ | ||
184 | .rreg = xreg_right, .shift = xshift, \ | ||
185 | .min = xmin, .max = xmax} } | ||
186 | |||
187 | |||
173 | /* | 188 | /* |
174 | * Simplified versions of above macros, declaring a struct and calculating | 189 | * Simplified versions of above macros, declaring a struct and calculating |
175 | * ARRAY_SIZE internally | 190 | * ARRAY_SIZE internally |
@@ -329,6 +344,12 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, | |||
329 | struct snd_ctl_elem_value *ucontrol); | 344 | struct snd_ctl_elem_value *ucontrol); |
330 | int snd_soc_limit_volume(struct snd_soc_codec *codec, | 345 | int snd_soc_limit_volume(struct snd_soc_codec *codec, |
331 | const char *name, int max); | 346 | const char *name, int max); |
347 | int snd_soc_info_volsw_2r_sx(struct snd_kcontrol *kcontrol, | ||
348 | struct snd_ctl_elem_info *uinfo); | ||
349 | int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol, | ||
350 | struct snd_ctl_elem_value *ucontrol); | ||
351 | int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol, | ||
352 | struct snd_ctl_elem_value *ucontrol); | ||
332 | 353 | ||
333 | /** | 354 | /** |
334 | * struct snd_soc_jack_pin - Describes a pin to update based on jack detection | 355 | * struct snd_soc_jack_pin - Describes a pin to update based on jack detection |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index e1043f644730..6220bc1ee427 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -2352,6 +2352,101 @@ int snd_soc_limit_volume(struct snd_soc_codec *codec, | |||
2352 | EXPORT_SYMBOL_GPL(snd_soc_limit_volume); | 2352 | EXPORT_SYMBOL_GPL(snd_soc_limit_volume); |
2353 | 2353 | ||
2354 | /** | 2354 | /** |
2355 | * snd_soc_info_volsw_2r_sx - double with tlv and variable data size | ||
2356 | * mixer info callback | ||
2357 | * @kcontrol: mixer control | ||
2358 | * @uinfo: control element information | ||
2359 | * | ||
2360 | * Returns 0 for success. | ||
2361 | */ | ||
2362 | int snd_soc_info_volsw_2r_sx(struct snd_kcontrol *kcontrol, | ||
2363 | struct snd_ctl_elem_info *uinfo) | ||
2364 | { | ||
2365 | struct soc_mixer_control *mc = | ||
2366 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2367 | int max = mc->max; | ||
2368 | int min = mc->min; | ||
2369 | |||
2370 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2371 | uinfo->count = 2; | ||
2372 | uinfo->value.integer.min = 0; | ||
2373 | uinfo->value.integer.max = max-min; | ||
2374 | |||
2375 | return 0; | ||
2376 | } | ||
2377 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r_sx); | ||
2378 | |||
2379 | /** | ||
2380 | * snd_soc_get_volsw_2r_sx - double with tlv and variable data size | ||
2381 | * mixer get callback | ||
2382 | * @kcontrol: mixer control | ||
2383 | * @uinfo: control element information | ||
2384 | * | ||
2385 | * Returns 0 for success. | ||
2386 | */ | ||
2387 | int snd_soc_get_volsw_2r_sx(struct snd_kcontrol *kcontrol, | ||
2388 | struct snd_ctl_elem_value *ucontrol) | ||
2389 | { | ||
2390 | struct soc_mixer_control *mc = | ||
2391 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2392 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2393 | unsigned int mask = (1<<mc->shift)-1; | ||
2394 | int min = mc->min; | ||
2395 | int val = snd_soc_read(codec, mc->reg) & mask; | ||
2396 | int valr = snd_soc_read(codec, mc->rreg) & mask; | ||
2397 | |||
2398 | ucontrol->value.integer.value[0] = ((val & 0xff)-min); | ||
2399 | ucontrol->value.integer.value[1] = ((valr & 0xff)-min); | ||
2400 | return 0; | ||
2401 | } | ||
2402 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r_sx); | ||
2403 | |||
2404 | /** | ||
2405 | * snd_soc_put_volsw_2r_sx - double with tlv and variable data size | ||
2406 | * mixer put callback | ||
2407 | * @kcontrol: mixer control | ||
2408 | * @uinfo: control element information | ||
2409 | * | ||
2410 | * Returns 0 for success. | ||
2411 | */ | ||
2412 | int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol, | ||
2413 | struct snd_ctl_elem_value *ucontrol) | ||
2414 | { | ||
2415 | struct soc_mixer_control *mc = | ||
2416 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2417 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2418 | unsigned int mask = (1<<mc->shift)-1; | ||
2419 | int min = mc->min; | ||
2420 | int ret; | ||
2421 | unsigned int val, valr, oval, ovalr; | ||
2422 | |||
2423 | val = ((ucontrol->value.integer.value[0]+min) & 0xff); | ||
2424 | val &= mask; | ||
2425 | valr = ((ucontrol->value.integer.value[1]+min) & 0xff); | ||
2426 | valr &= mask; | ||
2427 | |||
2428 | oval = snd_soc_read(codec, mc->reg) & mask; | ||
2429 | ovalr = snd_soc_read(codec, mc->rreg) & mask; | ||
2430 | |||
2431 | ret = 0; | ||
2432 | if (oval != val) { | ||
2433 | ret = snd_soc_write(codec, mc->reg, val); | ||
2434 | if (ret < 0) | ||
2435 | return 0; | ||
2436 | ret = 1; | ||
2437 | } | ||
2438 | if (ovalr != valr) { | ||
2439 | ret = snd_soc_write(codec, mc->rreg, valr); | ||
2440 | if (ret < 0) | ||
2441 | return 0; | ||
2442 | ret = 1; | ||
2443 | } | ||
2444 | |||
2445 | return 0; | ||
2446 | } | ||
2447 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx); | ||
2448 | |||
2449 | /** | ||
2355 | * snd_soc_dai_set_sysclk - configure DAI system or master clock. | 2450 | * snd_soc_dai_set_sysclk - configure DAI system or master clock. |
2356 | * @dai: DAI | 2451 | * @dai: DAI |
2357 | * @clk_id: DAI specific clock ID | 2452 | * @clk_id: DAI specific clock ID |