17077148fSMark Brown /* 27077148fSMark Brown * soc-ops.c -- Generic ASoC operations 37077148fSMark Brown * 47077148fSMark Brown * Copyright 2005 Wolfson Microelectronics PLC. 57077148fSMark Brown * Copyright 2005 Openedhand Ltd. 67077148fSMark Brown * Copyright (C) 2010 Slimlogic Ltd. 77077148fSMark Brown * Copyright (C) 2010 Texas Instruments Inc. 87077148fSMark Brown * 97077148fSMark Brown * Author: Liam Girdwood <lrg@slimlogic.co.uk> 107077148fSMark Brown * with code, comments and ideas from :- 117077148fSMark Brown * Richard Purdie <richard@openedhand.com> 127077148fSMark Brown * 137077148fSMark Brown * This program is free software; you can redistribute it and/or modify it 147077148fSMark Brown * under the terms of the GNU General Public License as published by the 157077148fSMark Brown * Free Software Foundation; either version 2 of the License, or (at your 167077148fSMark Brown * option) any later version. 177077148fSMark Brown */ 187077148fSMark Brown 197077148fSMark Brown #include <linux/module.h> 207077148fSMark Brown #include <linux/moduleparam.h> 217077148fSMark Brown #include <linux/init.h> 227077148fSMark Brown #include <linux/delay.h> 237077148fSMark Brown #include <linux/pm.h> 247077148fSMark Brown #include <linux/bitops.h> 257077148fSMark Brown #include <linux/ctype.h> 267077148fSMark Brown #include <linux/slab.h> 277077148fSMark Brown #include <sound/core.h> 287077148fSMark Brown #include <sound/jack.h> 297077148fSMark Brown #include <sound/pcm.h> 307077148fSMark Brown #include <sound/pcm_params.h> 317077148fSMark Brown #include <sound/soc.h> 327077148fSMark Brown #include <sound/soc-dpcm.h> 337077148fSMark Brown #include <sound/initval.h> 347077148fSMark Brown 357077148fSMark Brown /** 367077148fSMark Brown * snd_soc_info_enum_double - enumerated double mixer info callback 377077148fSMark Brown * @kcontrol: mixer control 387077148fSMark Brown * @uinfo: control element information 397077148fSMark Brown * 407077148fSMark Brown * Callback to provide information about a double enumerated 417077148fSMark Brown * mixer control. 427077148fSMark Brown * 437077148fSMark Brown * Returns 0 for success. 447077148fSMark Brown */ 457077148fSMark Brown int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, 467077148fSMark Brown struct snd_ctl_elem_info *uinfo) 477077148fSMark Brown { 487077148fSMark Brown struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 497077148fSMark Brown 507077148fSMark Brown return snd_ctl_enum_info(uinfo, e->shift_l == e->shift_r ? 1 : 2, 517077148fSMark Brown e->items, e->texts); 527077148fSMark Brown } 537077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_enum_double); 547077148fSMark Brown 557077148fSMark Brown /** 567077148fSMark Brown * snd_soc_get_enum_double - enumerated double mixer get callback 577077148fSMark Brown * @kcontrol: mixer control 587077148fSMark Brown * @ucontrol: control element information 597077148fSMark Brown * 607077148fSMark Brown * Callback to get the value of a double enumerated mixer. 617077148fSMark Brown * 627077148fSMark Brown * Returns 0 for success. 637077148fSMark Brown */ 647077148fSMark Brown int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, 657077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 667077148fSMark Brown { 677077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 687077148fSMark Brown struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 697077148fSMark Brown unsigned int val, item; 707077148fSMark Brown unsigned int reg_val; 717077148fSMark Brown int ret; 727077148fSMark Brown 737077148fSMark Brown ret = snd_soc_component_read(component, e->reg, ®_val); 747077148fSMark Brown if (ret) 757077148fSMark Brown return ret; 767077148fSMark Brown val = (reg_val >> e->shift_l) & e->mask; 777077148fSMark Brown item = snd_soc_enum_val_to_item(e, val); 787077148fSMark Brown ucontrol->value.enumerated.item[0] = item; 797077148fSMark Brown if (e->shift_l != e->shift_r) { 807077148fSMark Brown val = (reg_val >> e->shift_l) & e->mask; 817077148fSMark Brown item = snd_soc_enum_val_to_item(e, val); 827077148fSMark Brown ucontrol->value.enumerated.item[1] = item; 837077148fSMark Brown } 847077148fSMark Brown 857077148fSMark Brown return 0; 867077148fSMark Brown } 877077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_enum_double); 887077148fSMark Brown 897077148fSMark Brown /** 907077148fSMark Brown * snd_soc_put_enum_double - enumerated double mixer put callback 917077148fSMark Brown * @kcontrol: mixer control 927077148fSMark Brown * @ucontrol: control element information 937077148fSMark Brown * 947077148fSMark Brown * Callback to set the value of a double enumerated mixer. 957077148fSMark Brown * 967077148fSMark Brown * Returns 0 for success. 977077148fSMark Brown */ 987077148fSMark Brown int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, 997077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 1007077148fSMark Brown { 1017077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 1027077148fSMark Brown struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1037077148fSMark Brown unsigned int *item = ucontrol->value.enumerated.item; 1047077148fSMark Brown unsigned int val; 1057077148fSMark Brown unsigned int mask; 1067077148fSMark Brown 1077077148fSMark Brown if (item[0] >= e->items) 1087077148fSMark Brown return -EINVAL; 1097077148fSMark Brown val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; 1107077148fSMark Brown mask = e->mask << e->shift_l; 1117077148fSMark Brown if (e->shift_l != e->shift_r) { 1127077148fSMark Brown if (item[1] >= e->items) 1137077148fSMark Brown return -EINVAL; 1147077148fSMark Brown val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; 1157077148fSMark Brown mask |= e->mask << e->shift_r; 1167077148fSMark Brown } 1177077148fSMark Brown 1187077148fSMark Brown return snd_soc_component_update_bits(component, e->reg, mask, val); 1197077148fSMark Brown } 1207077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); 1217077148fSMark Brown 1227077148fSMark Brown /** 1237077148fSMark Brown * snd_soc_read_signed - Read a codec register and interprete as signed value 1247077148fSMark Brown * @component: component 1257077148fSMark Brown * @reg: Register to read 1267077148fSMark Brown * @mask: Mask to use after shifting the register value 1277077148fSMark Brown * @shift: Right shift of register value 1287077148fSMark Brown * @sign_bit: Bit that describes if a number is negative or not. 1297077148fSMark Brown * @signed_val: Pointer to where the read value should be stored 1307077148fSMark Brown * 1317077148fSMark Brown * This functions reads a codec register. The register value is shifted right 1327077148fSMark Brown * by 'shift' bits and masked with the given 'mask'. Afterwards it translates 1337077148fSMark Brown * the given registervalue into a signed integer if sign_bit is non-zero. 1347077148fSMark Brown * 1357077148fSMark Brown * Returns 0 on sucess, otherwise an error value 1367077148fSMark Brown */ 1377077148fSMark Brown static int snd_soc_read_signed(struct snd_soc_component *component, 1387077148fSMark Brown unsigned int reg, unsigned int mask, unsigned int shift, 1397077148fSMark Brown unsigned int sign_bit, int *signed_val) 1407077148fSMark Brown { 1417077148fSMark Brown int ret; 1427077148fSMark Brown unsigned int val; 1437077148fSMark Brown 1447077148fSMark Brown ret = snd_soc_component_read(component, reg, &val); 1457077148fSMark Brown if (ret < 0) 1467077148fSMark Brown return ret; 1477077148fSMark Brown 1487077148fSMark Brown val = (val >> shift) & mask; 1497077148fSMark Brown 1507077148fSMark Brown if (!sign_bit) { 1517077148fSMark Brown *signed_val = val; 1527077148fSMark Brown return 0; 1537077148fSMark Brown } 1547077148fSMark Brown 1557077148fSMark Brown /* non-negative number */ 1567077148fSMark Brown if (!(val & BIT(sign_bit))) { 1577077148fSMark Brown *signed_val = val; 1587077148fSMark Brown return 0; 1597077148fSMark Brown } 1607077148fSMark Brown 1617077148fSMark Brown ret = val; 1627077148fSMark Brown 1637077148fSMark Brown /* 1647077148fSMark Brown * The register most probably does not contain a full-sized int. 1657077148fSMark Brown * Instead we have an arbitrary number of bits in a signed 1667077148fSMark Brown * representation which has to be translated into a full-sized int. 1677077148fSMark Brown * This is done by filling up all bits above the sign-bit. 1687077148fSMark Brown */ 1697077148fSMark Brown ret |= ~((int)(BIT(sign_bit) - 1)); 1707077148fSMark Brown 1717077148fSMark Brown *signed_val = ret; 1727077148fSMark Brown 1737077148fSMark Brown return 0; 1747077148fSMark Brown } 1757077148fSMark Brown 1767077148fSMark Brown /** 1777077148fSMark Brown * snd_soc_info_volsw - single mixer info callback 1787077148fSMark Brown * @kcontrol: mixer control 1797077148fSMark Brown * @uinfo: control element information 1807077148fSMark Brown * 1817077148fSMark Brown * Callback to provide information about a single mixer control, or a double 1827077148fSMark Brown * mixer control that spans 2 registers. 1837077148fSMark Brown * 1847077148fSMark Brown * Returns 0 for success. 1857077148fSMark Brown */ 1867077148fSMark Brown int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, 1877077148fSMark Brown struct snd_ctl_elem_info *uinfo) 1887077148fSMark Brown { 1897077148fSMark Brown struct soc_mixer_control *mc = 1907077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 1917077148fSMark Brown int platform_max; 1927077148fSMark Brown 1937077148fSMark Brown if (!mc->platform_max) 1947077148fSMark Brown mc->platform_max = mc->max; 1957077148fSMark Brown platform_max = mc->platform_max; 1967077148fSMark Brown 1977077148fSMark Brown if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume")) 1987077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1997077148fSMark Brown else 2007077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2017077148fSMark Brown 2027077148fSMark Brown uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; 2037077148fSMark Brown uinfo->value.integer.min = 0; 2047077148fSMark Brown uinfo->value.integer.max = platform_max - mc->min; 2057077148fSMark Brown return 0; 2067077148fSMark Brown } 2077077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw); 2087077148fSMark Brown 2097077148fSMark Brown /** 2107077148fSMark Brown * snd_soc_get_volsw - single mixer get callback 2117077148fSMark Brown * @kcontrol: mixer control 2127077148fSMark Brown * @ucontrol: control element information 2137077148fSMark Brown * 2147077148fSMark Brown * Callback to get the value of a single mixer control, or a double mixer 2157077148fSMark Brown * control that spans 2 registers. 2167077148fSMark Brown * 2177077148fSMark Brown * Returns 0 for success. 2187077148fSMark Brown */ 2197077148fSMark Brown int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, 2207077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 2217077148fSMark Brown { 2227077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 2237077148fSMark Brown struct soc_mixer_control *mc = 2247077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 2257077148fSMark Brown unsigned int reg = mc->reg; 2267077148fSMark Brown unsigned int reg2 = mc->rreg; 2277077148fSMark Brown unsigned int shift = mc->shift; 2287077148fSMark Brown unsigned int rshift = mc->rshift; 2297077148fSMark Brown int max = mc->max; 2307077148fSMark Brown int min = mc->min; 2317077148fSMark Brown int sign_bit = mc->sign_bit; 2327077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 2337077148fSMark Brown unsigned int invert = mc->invert; 2347077148fSMark Brown int val; 2357077148fSMark Brown int ret; 2367077148fSMark Brown 2377077148fSMark Brown if (sign_bit) 2387077148fSMark Brown mask = BIT(sign_bit + 1) - 1; 2397077148fSMark Brown 2407077148fSMark Brown ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); 2417077148fSMark Brown if (ret) 2427077148fSMark Brown return ret; 2437077148fSMark Brown 2447077148fSMark Brown ucontrol->value.integer.value[0] = val - min; 2457077148fSMark Brown if (invert) 2467077148fSMark Brown ucontrol->value.integer.value[0] = 2477077148fSMark Brown max - ucontrol->value.integer.value[0]; 2487077148fSMark Brown 2497077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 2507077148fSMark Brown if (reg == reg2) 2517077148fSMark Brown ret = snd_soc_read_signed(component, reg, mask, rshift, 2527077148fSMark Brown sign_bit, &val); 2537077148fSMark Brown else 2547077148fSMark Brown ret = snd_soc_read_signed(component, reg2, mask, shift, 2557077148fSMark Brown sign_bit, &val); 2567077148fSMark Brown if (ret) 2577077148fSMark Brown return ret; 2587077148fSMark Brown 2597077148fSMark Brown ucontrol->value.integer.value[1] = val - min; 2607077148fSMark Brown if (invert) 2617077148fSMark Brown ucontrol->value.integer.value[1] = 2627077148fSMark Brown max - ucontrol->value.integer.value[1]; 2637077148fSMark Brown } 2647077148fSMark Brown 2657077148fSMark Brown return 0; 2667077148fSMark Brown } 2677077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw); 2687077148fSMark Brown 2697077148fSMark Brown /** 2707077148fSMark Brown * snd_soc_put_volsw - single mixer put callback 2717077148fSMark Brown * @kcontrol: mixer control 2727077148fSMark Brown * @ucontrol: control element information 2737077148fSMark Brown * 2747077148fSMark Brown * Callback to set the value of a single mixer control, or a double mixer 2757077148fSMark Brown * control that spans 2 registers. 2767077148fSMark Brown * 2777077148fSMark Brown * Returns 0 for success. 2787077148fSMark Brown */ 2797077148fSMark Brown int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, 2807077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 2817077148fSMark Brown { 2827077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 2837077148fSMark Brown struct soc_mixer_control *mc = 2847077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 2857077148fSMark Brown unsigned int reg = mc->reg; 2867077148fSMark Brown unsigned int reg2 = mc->rreg; 2877077148fSMark Brown unsigned int shift = mc->shift; 2887077148fSMark Brown unsigned int rshift = mc->rshift; 2897077148fSMark Brown int max = mc->max; 2907077148fSMark Brown int min = mc->min; 2917077148fSMark Brown unsigned int sign_bit = mc->sign_bit; 2927077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 2937077148fSMark Brown unsigned int invert = mc->invert; 2947077148fSMark Brown int err; 2957077148fSMark Brown bool type_2r = false; 2967077148fSMark Brown unsigned int val2 = 0; 2977077148fSMark Brown unsigned int val, val_mask; 2987077148fSMark Brown 2997077148fSMark Brown if (sign_bit) 3007077148fSMark Brown mask = BIT(sign_bit + 1) - 1; 3017077148fSMark Brown 3027077148fSMark Brown val = ((ucontrol->value.integer.value[0] + min) & mask); 3037077148fSMark Brown if (invert) 3047077148fSMark Brown val = max - val; 3057077148fSMark Brown val_mask = mask << shift; 3067077148fSMark Brown val = val << shift; 3077077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 3087077148fSMark Brown val2 = ((ucontrol->value.integer.value[1] + min) & mask); 3097077148fSMark Brown if (invert) 3107077148fSMark Brown val2 = max - val2; 3117077148fSMark Brown if (reg == reg2) { 3127077148fSMark Brown val_mask |= mask << rshift; 3137077148fSMark Brown val |= val2 << rshift; 3147077148fSMark Brown } else { 3157077148fSMark Brown val2 = val2 << shift; 3167077148fSMark Brown type_2r = true; 3177077148fSMark Brown } 3187077148fSMark Brown } 3197077148fSMark Brown err = snd_soc_component_update_bits(component, reg, val_mask, val); 3207077148fSMark Brown if (err < 0) 3217077148fSMark Brown return err; 3227077148fSMark Brown 3237077148fSMark Brown if (type_2r) 3247077148fSMark Brown err = snd_soc_component_update_bits(component, reg2, val_mask, 3257077148fSMark Brown val2); 3267077148fSMark Brown 3277077148fSMark Brown return err; 3287077148fSMark Brown } 3297077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw); 3307077148fSMark Brown 3317077148fSMark Brown /** 3327077148fSMark Brown * snd_soc_get_volsw_sx - single mixer get callback 3337077148fSMark Brown * @kcontrol: mixer control 3347077148fSMark Brown * @ucontrol: control element information 3357077148fSMark Brown * 3367077148fSMark Brown * Callback to get the value of a single mixer control, or a double mixer 3377077148fSMark Brown * control that spans 2 registers. 3387077148fSMark Brown * 3397077148fSMark Brown * Returns 0 for success. 3407077148fSMark Brown */ 3417077148fSMark Brown int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, 3427077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 3437077148fSMark Brown { 3447077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 3457077148fSMark Brown struct soc_mixer_control *mc = 3467077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 3477077148fSMark Brown unsigned int reg = mc->reg; 3487077148fSMark Brown unsigned int reg2 = mc->rreg; 3497077148fSMark Brown unsigned int shift = mc->shift; 3507077148fSMark Brown unsigned int rshift = mc->rshift; 3517077148fSMark Brown int max = mc->max; 3527077148fSMark Brown int min = mc->min; 3537077148fSMark Brown int mask = (1 << (fls(min + max) - 1)) - 1; 3547077148fSMark Brown unsigned int val; 3557077148fSMark Brown int ret; 3567077148fSMark Brown 3577077148fSMark Brown ret = snd_soc_component_read(component, reg, &val); 3587077148fSMark Brown if (ret < 0) 3597077148fSMark Brown return ret; 3607077148fSMark Brown 3617077148fSMark Brown ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; 3627077148fSMark Brown 3637077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 3647077148fSMark Brown ret = snd_soc_component_read(component, reg2, &val); 3657077148fSMark Brown if (ret < 0) 3667077148fSMark Brown return ret; 3677077148fSMark Brown 3687077148fSMark Brown val = ((val >> rshift) - min) & mask; 3697077148fSMark Brown ucontrol->value.integer.value[1] = val; 3707077148fSMark Brown } 3717077148fSMark Brown 3727077148fSMark Brown return 0; 3737077148fSMark Brown } 3747077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx); 3757077148fSMark Brown 3767077148fSMark Brown /** 3777077148fSMark Brown * snd_soc_put_volsw_sx - double mixer set callback 3787077148fSMark Brown * @kcontrol: mixer control 3797077148fSMark Brown * @uinfo: control element information 3807077148fSMark Brown * 3817077148fSMark Brown * Callback to set the value of a double mixer control that spans 2 registers. 3827077148fSMark Brown * 3837077148fSMark Brown * Returns 0 for success. 3847077148fSMark Brown */ 3857077148fSMark Brown int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, 3867077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 3877077148fSMark Brown { 3887077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 3897077148fSMark Brown struct soc_mixer_control *mc = 3907077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 3917077148fSMark Brown 3927077148fSMark Brown unsigned int reg = mc->reg; 3937077148fSMark Brown unsigned int reg2 = mc->rreg; 3947077148fSMark Brown unsigned int shift = mc->shift; 3957077148fSMark Brown unsigned int rshift = mc->rshift; 3967077148fSMark Brown int max = mc->max; 3977077148fSMark Brown int min = mc->min; 3987077148fSMark Brown int mask = (1 << (fls(min + max) - 1)) - 1; 3997077148fSMark Brown int err = 0; 4007077148fSMark Brown unsigned int val, val_mask, val2 = 0; 4017077148fSMark Brown 4027077148fSMark Brown val_mask = mask << shift; 4037077148fSMark Brown val = (ucontrol->value.integer.value[0] + min) & mask; 4047077148fSMark Brown val = val << shift; 4057077148fSMark Brown 4067077148fSMark Brown err = snd_soc_component_update_bits(component, reg, val_mask, val); 4077077148fSMark Brown if (err < 0) 4087077148fSMark Brown return err; 4097077148fSMark Brown 4107077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 4117077148fSMark Brown val_mask = mask << rshift; 4127077148fSMark Brown val2 = (ucontrol->value.integer.value[1] + min) & mask; 4137077148fSMark Brown val2 = val2 << rshift; 4147077148fSMark Brown 4157077148fSMark Brown err = snd_soc_component_update_bits(component, reg2, val_mask, 4167077148fSMark Brown val2); 4177077148fSMark Brown } 4187077148fSMark Brown return err; 4197077148fSMark Brown } 4207077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); 4217077148fSMark Brown 4227077148fSMark Brown /** 4237077148fSMark Brown * snd_soc_info_volsw_range - single mixer info callback with range. 4247077148fSMark Brown * @kcontrol: mixer control 4257077148fSMark Brown * @uinfo: control element information 4267077148fSMark Brown * 4277077148fSMark Brown * Callback to provide information, within a range, about a single 4287077148fSMark Brown * mixer control. 4297077148fSMark Brown * 4307077148fSMark Brown * returns 0 for success. 4317077148fSMark Brown */ 4327077148fSMark Brown int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, 4337077148fSMark Brown struct snd_ctl_elem_info *uinfo) 4347077148fSMark Brown { 4357077148fSMark Brown struct soc_mixer_control *mc = 4367077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 4377077148fSMark Brown int platform_max; 4387077148fSMark Brown int min = mc->min; 4397077148fSMark Brown 4407077148fSMark Brown if (!mc->platform_max) 4417077148fSMark Brown mc->platform_max = mc->max; 4427077148fSMark Brown platform_max = mc->platform_max; 4437077148fSMark Brown 4447077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 4457077148fSMark Brown uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; 4467077148fSMark Brown uinfo->value.integer.min = 0; 4477077148fSMark Brown uinfo->value.integer.max = platform_max - min; 4487077148fSMark Brown 4497077148fSMark Brown return 0; 4507077148fSMark Brown } 4517077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); 4527077148fSMark Brown 4537077148fSMark Brown /** 4547077148fSMark Brown * snd_soc_put_volsw_range - single mixer put value callback with range. 4557077148fSMark Brown * @kcontrol: mixer control 4567077148fSMark Brown * @ucontrol: control element information 4577077148fSMark Brown * 4587077148fSMark Brown * Callback to set the value, within a range, for a single mixer control. 4597077148fSMark Brown * 4607077148fSMark Brown * Returns 0 for success. 4617077148fSMark Brown */ 4627077148fSMark Brown int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, 4637077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 4647077148fSMark Brown { 4657077148fSMark Brown struct soc_mixer_control *mc = 4667077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 4677077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 4687077148fSMark Brown unsigned int reg = mc->reg; 4697077148fSMark Brown unsigned int rreg = mc->rreg; 4707077148fSMark Brown unsigned int shift = mc->shift; 4717077148fSMark Brown int min = mc->min; 4727077148fSMark Brown int max = mc->max; 4737077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 4747077148fSMark Brown unsigned int invert = mc->invert; 4757077148fSMark Brown unsigned int val, val_mask; 4767077148fSMark Brown int ret; 4777077148fSMark Brown 4787077148fSMark Brown if (invert) 4797077148fSMark Brown val = (max - ucontrol->value.integer.value[0]) & mask; 4807077148fSMark Brown else 4817077148fSMark Brown val = ((ucontrol->value.integer.value[0] + min) & mask); 4827077148fSMark Brown val_mask = mask << shift; 4837077148fSMark Brown val = val << shift; 4847077148fSMark Brown 4857077148fSMark Brown ret = snd_soc_component_update_bits(component, reg, val_mask, val); 4867077148fSMark Brown if (ret < 0) 4877077148fSMark Brown return ret; 4887077148fSMark Brown 4897077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 4907077148fSMark Brown if (invert) 4917077148fSMark Brown val = (max - ucontrol->value.integer.value[1]) & mask; 4927077148fSMark Brown else 4937077148fSMark Brown val = ((ucontrol->value.integer.value[1] + min) & mask); 4947077148fSMark Brown val_mask = mask << shift; 4957077148fSMark Brown val = val << shift; 4967077148fSMark Brown 4977077148fSMark Brown ret = snd_soc_component_update_bits(component, rreg, val_mask, 4987077148fSMark Brown val); 4997077148fSMark Brown } 5007077148fSMark Brown 5017077148fSMark Brown return ret; 5027077148fSMark Brown } 5037077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); 5047077148fSMark Brown 5057077148fSMark Brown /** 5067077148fSMark Brown * snd_soc_get_volsw_range - single mixer get callback with range 5077077148fSMark Brown * @kcontrol: mixer control 5087077148fSMark Brown * @ucontrol: control element information 5097077148fSMark Brown * 5107077148fSMark Brown * Callback to get the value, within a range, of a single mixer control. 5117077148fSMark Brown * 5127077148fSMark Brown * Returns 0 for success. 5137077148fSMark Brown */ 5147077148fSMark Brown int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, 5157077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 5167077148fSMark Brown { 5177077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 5187077148fSMark Brown struct soc_mixer_control *mc = 5197077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 5207077148fSMark Brown unsigned int reg = mc->reg; 5217077148fSMark Brown unsigned int rreg = mc->rreg; 5227077148fSMark Brown unsigned int shift = mc->shift; 5237077148fSMark Brown int min = mc->min; 5247077148fSMark Brown int max = mc->max; 5257077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 5267077148fSMark Brown unsigned int invert = mc->invert; 5277077148fSMark Brown unsigned int val; 5287077148fSMark Brown int ret; 5297077148fSMark Brown 5307077148fSMark Brown ret = snd_soc_component_read(component, reg, &val); 5317077148fSMark Brown if (ret) 5327077148fSMark Brown return ret; 5337077148fSMark Brown 5347077148fSMark Brown ucontrol->value.integer.value[0] = (val >> shift) & mask; 5357077148fSMark Brown if (invert) 5367077148fSMark Brown ucontrol->value.integer.value[0] = 5377077148fSMark Brown max - ucontrol->value.integer.value[0]; 5387077148fSMark Brown else 5397077148fSMark Brown ucontrol->value.integer.value[0] = 5407077148fSMark Brown ucontrol->value.integer.value[0] - min; 5417077148fSMark Brown 5427077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 5437077148fSMark Brown ret = snd_soc_component_read(component, rreg, &val); 5447077148fSMark Brown if (ret) 5457077148fSMark Brown return ret; 5467077148fSMark Brown 5477077148fSMark Brown ucontrol->value.integer.value[1] = (val >> shift) & mask; 5487077148fSMark Brown if (invert) 5497077148fSMark Brown ucontrol->value.integer.value[1] = 5507077148fSMark Brown max - ucontrol->value.integer.value[1]; 5517077148fSMark Brown else 5527077148fSMark Brown ucontrol->value.integer.value[1] = 5537077148fSMark Brown ucontrol->value.integer.value[1] - min; 5547077148fSMark Brown } 5557077148fSMark Brown 5567077148fSMark Brown return 0; 5577077148fSMark Brown } 5587077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); 5597077148fSMark Brown 5607077148fSMark Brown /** 5617077148fSMark Brown * snd_soc_limit_volume - Set new limit to an existing volume control. 5627077148fSMark Brown * 56326d9ca34SLars-Peter Clausen * @card: where to look for the control 5647077148fSMark Brown * @name: Name of the control 5657077148fSMark Brown * @max: new maximum limit 5667077148fSMark Brown * 5677077148fSMark Brown * Return 0 for success, else error. 5687077148fSMark Brown */ 56926d9ca34SLars-Peter Clausen int snd_soc_limit_volume(struct snd_soc_card *card, 5707077148fSMark Brown const char *name, int max) 5717077148fSMark Brown { 57226d9ca34SLars-Peter Clausen struct snd_card *snd_card = card->snd_card; 5737077148fSMark Brown struct snd_kcontrol *kctl; 5747077148fSMark Brown struct soc_mixer_control *mc; 5757077148fSMark Brown int found = 0; 5767077148fSMark Brown int ret = -EINVAL; 5777077148fSMark Brown 5787077148fSMark Brown /* Sanity check for name and max */ 5797077148fSMark Brown if (unlikely(!name || max <= 0)) 5807077148fSMark Brown return -EINVAL; 5817077148fSMark Brown 58226d9ca34SLars-Peter Clausen list_for_each_entry(kctl, &snd_card->controls, list) { 5837077148fSMark Brown if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) { 5847077148fSMark Brown found = 1; 5857077148fSMark Brown break; 5867077148fSMark Brown } 5877077148fSMark Brown } 5887077148fSMark Brown if (found) { 5897077148fSMark Brown mc = (struct soc_mixer_control *)kctl->private_value; 5907077148fSMark Brown if (max <= mc->max) { 5917077148fSMark Brown mc->platform_max = max; 5927077148fSMark Brown ret = 0; 5937077148fSMark Brown } 5947077148fSMark Brown } 5957077148fSMark Brown return ret; 5967077148fSMark Brown } 5977077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_limit_volume); 5987077148fSMark Brown 5997077148fSMark Brown int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, 6007077148fSMark Brown struct snd_ctl_elem_info *uinfo) 6017077148fSMark Brown { 6027077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 6037077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value; 6047077148fSMark Brown 6057077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 6067077148fSMark Brown uinfo->count = params->num_regs * component->val_bytes; 6077077148fSMark Brown 6087077148fSMark Brown return 0; 6097077148fSMark Brown } 6107077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info); 6117077148fSMark Brown 6127077148fSMark Brown int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, 6137077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 6147077148fSMark Brown { 6157077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 6167077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value; 6177077148fSMark Brown int ret; 6187077148fSMark Brown 6197077148fSMark Brown if (component->regmap) 6207077148fSMark Brown ret = regmap_raw_read(component->regmap, params->base, 6217077148fSMark Brown ucontrol->value.bytes.data, 6227077148fSMark Brown params->num_regs * component->val_bytes); 6237077148fSMark Brown else 6247077148fSMark Brown ret = -EINVAL; 6257077148fSMark Brown 6267077148fSMark Brown /* Hide any masked bytes to ensure consistent data reporting */ 6277077148fSMark Brown if (ret == 0 && params->mask) { 6287077148fSMark Brown switch (component->val_bytes) { 6297077148fSMark Brown case 1: 6307077148fSMark Brown ucontrol->value.bytes.data[0] &= ~params->mask; 6317077148fSMark Brown break; 6327077148fSMark Brown case 2: 6337077148fSMark Brown ((u16 *)(&ucontrol->value.bytes.data))[0] 6347077148fSMark Brown &= cpu_to_be16(~params->mask); 6357077148fSMark Brown break; 6367077148fSMark Brown case 4: 6377077148fSMark Brown ((u32 *)(&ucontrol->value.bytes.data))[0] 6387077148fSMark Brown &= cpu_to_be32(~params->mask); 6397077148fSMark Brown break; 6407077148fSMark Brown default: 6417077148fSMark Brown return -EINVAL; 6427077148fSMark Brown } 6437077148fSMark Brown } 6447077148fSMark Brown 6457077148fSMark Brown return ret; 6467077148fSMark Brown } 6477077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_get); 6487077148fSMark Brown 6497077148fSMark Brown int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, 6507077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 6517077148fSMark Brown { 6527077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 6537077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value; 6547077148fSMark Brown int ret, len; 6557077148fSMark Brown unsigned int val, mask; 6567077148fSMark Brown void *data; 6577077148fSMark Brown 6587077148fSMark Brown if (!component->regmap || !params->num_regs) 6597077148fSMark Brown return -EINVAL; 6607077148fSMark Brown 6617077148fSMark Brown len = params->num_regs * component->val_bytes; 6627077148fSMark Brown 6637077148fSMark Brown data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); 6647077148fSMark Brown if (!data) 6657077148fSMark Brown return -ENOMEM; 6667077148fSMark Brown 6677077148fSMark Brown /* 6687077148fSMark Brown * If we've got a mask then we need to preserve the register 6697077148fSMark Brown * bits. We shouldn't modify the incoming data so take a 6707077148fSMark Brown * copy. 6717077148fSMark Brown */ 6727077148fSMark Brown if (params->mask) { 6737077148fSMark Brown ret = regmap_read(component->regmap, params->base, &val); 6747077148fSMark Brown if (ret != 0) 6757077148fSMark Brown goto out; 6767077148fSMark Brown 6777077148fSMark Brown val &= params->mask; 6787077148fSMark Brown 6797077148fSMark Brown switch (component->val_bytes) { 6807077148fSMark Brown case 1: 6817077148fSMark Brown ((u8 *)data)[0] &= ~params->mask; 6827077148fSMark Brown ((u8 *)data)[0] |= val; 6837077148fSMark Brown break; 6847077148fSMark Brown case 2: 6857077148fSMark Brown mask = ~params->mask; 6867077148fSMark Brown ret = regmap_parse_val(component->regmap, 6877077148fSMark Brown &mask, &mask); 6887077148fSMark Brown if (ret != 0) 6897077148fSMark Brown goto out; 6907077148fSMark Brown 6917077148fSMark Brown ((u16 *)data)[0] &= mask; 6927077148fSMark Brown 6937077148fSMark Brown ret = regmap_parse_val(component->regmap, 6947077148fSMark Brown &val, &val); 6957077148fSMark Brown if (ret != 0) 6967077148fSMark Brown goto out; 6977077148fSMark Brown 6987077148fSMark Brown ((u16 *)data)[0] |= val; 6997077148fSMark Brown break; 7007077148fSMark Brown case 4: 7017077148fSMark Brown mask = ~params->mask; 7027077148fSMark Brown ret = regmap_parse_val(component->regmap, 7037077148fSMark Brown &mask, &mask); 7047077148fSMark Brown if (ret != 0) 7057077148fSMark Brown goto out; 7067077148fSMark Brown 7077077148fSMark Brown ((u32 *)data)[0] &= mask; 7087077148fSMark Brown 7097077148fSMark Brown ret = regmap_parse_val(component->regmap, 7107077148fSMark Brown &val, &val); 7117077148fSMark Brown if (ret != 0) 7127077148fSMark Brown goto out; 7137077148fSMark Brown 7147077148fSMark Brown ((u32 *)data)[0] |= val; 7157077148fSMark Brown break; 7167077148fSMark Brown default: 7177077148fSMark Brown ret = -EINVAL; 7187077148fSMark Brown goto out; 7197077148fSMark Brown } 7207077148fSMark Brown } 7217077148fSMark Brown 7227077148fSMark Brown ret = regmap_raw_write(component->regmap, params->base, 7237077148fSMark Brown data, len); 7247077148fSMark Brown 7257077148fSMark Brown out: 7267077148fSMark Brown kfree(data); 7277077148fSMark Brown 7287077148fSMark Brown return ret; 7297077148fSMark Brown } 7307077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_put); 7317077148fSMark Brown 7327077148fSMark Brown int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, 7337077148fSMark Brown struct snd_ctl_elem_info *ucontrol) 7347077148fSMark Brown { 7357077148fSMark Brown struct soc_bytes_ext *params = (void *)kcontrol->private_value; 7367077148fSMark Brown 7377077148fSMark Brown ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; 7387077148fSMark Brown ucontrol->count = params->max; 7397077148fSMark Brown 7407077148fSMark Brown return 0; 7417077148fSMark Brown } 7427077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); 7437077148fSMark Brown 7447077148fSMark Brown int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, 7457077148fSMark Brown unsigned int size, unsigned int __user *tlv) 7467077148fSMark Brown { 7477077148fSMark Brown struct soc_bytes_ext *params = (void *)kcontrol->private_value; 7487077148fSMark Brown unsigned int count = size < params->max ? size : params->max; 7497077148fSMark Brown int ret = -ENXIO; 7507077148fSMark Brown 7517077148fSMark Brown switch (op_flag) { 7527077148fSMark Brown case SNDRV_CTL_TLV_OP_READ: 7537077148fSMark Brown if (params->get) 7547077148fSMark Brown ret = params->get(tlv, count); 7557077148fSMark Brown break; 7567077148fSMark Brown case SNDRV_CTL_TLV_OP_WRITE: 7577077148fSMark Brown if (params->put) 7587077148fSMark Brown ret = params->put(tlv, count); 7597077148fSMark Brown break; 7607077148fSMark Brown } 7617077148fSMark Brown return ret; 7627077148fSMark Brown } 7637077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); 7647077148fSMark Brown 7657077148fSMark Brown /** 7667077148fSMark Brown * snd_soc_info_xr_sx - signed multi register info callback 7677077148fSMark Brown * @kcontrol: mreg control 7687077148fSMark Brown * @uinfo: control element information 7697077148fSMark Brown * 7707077148fSMark Brown * Callback to provide information of a control that can 7717077148fSMark Brown * span multiple codec registers which together 7727077148fSMark Brown * forms a single signed value in a MSB/LSB manner. 7737077148fSMark Brown * 7747077148fSMark Brown * Returns 0 for success. 7757077148fSMark Brown */ 7767077148fSMark Brown int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, 7777077148fSMark Brown struct snd_ctl_elem_info *uinfo) 7787077148fSMark Brown { 7797077148fSMark Brown struct soc_mreg_control *mc = 7807077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value; 7817077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 7827077148fSMark Brown uinfo->count = 1; 7837077148fSMark Brown uinfo->value.integer.min = mc->min; 7847077148fSMark Brown uinfo->value.integer.max = mc->max; 7857077148fSMark Brown 7867077148fSMark Brown return 0; 7877077148fSMark Brown } 7887077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx); 7897077148fSMark Brown 7907077148fSMark Brown /** 7917077148fSMark Brown * snd_soc_get_xr_sx - signed multi register get callback 7927077148fSMark Brown * @kcontrol: mreg control 7937077148fSMark Brown * @ucontrol: control element information 7947077148fSMark Brown * 7957077148fSMark Brown * Callback to get the value of a control that can span 7967077148fSMark Brown * multiple codec registers which together forms a single 7977077148fSMark Brown * signed value in a MSB/LSB manner. The control supports 7987077148fSMark Brown * specifying total no of bits used to allow for bitfields 7997077148fSMark Brown * across the multiple codec registers. 8007077148fSMark Brown * 8017077148fSMark Brown * Returns 0 for success. 8027077148fSMark Brown */ 8037077148fSMark Brown int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, 8047077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 8057077148fSMark Brown { 8067077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 8077077148fSMark Brown struct soc_mreg_control *mc = 8087077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value; 8097077148fSMark Brown unsigned int regbase = mc->regbase; 8107077148fSMark Brown unsigned int regcount = mc->regcount; 8117077148fSMark Brown unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; 8127077148fSMark Brown unsigned int regwmask = (1<<regwshift)-1; 8137077148fSMark Brown unsigned int invert = mc->invert; 8147077148fSMark Brown unsigned long mask = (1UL<<mc->nbits)-1; 8157077148fSMark Brown long min = mc->min; 8167077148fSMark Brown long max = mc->max; 8177077148fSMark Brown long val = 0; 8187077148fSMark Brown unsigned int regval; 8197077148fSMark Brown unsigned int i; 8207077148fSMark Brown int ret; 8217077148fSMark Brown 8227077148fSMark Brown for (i = 0; i < regcount; i++) { 8237077148fSMark Brown ret = snd_soc_component_read(component, regbase+i, ®val); 8247077148fSMark Brown if (ret) 8257077148fSMark Brown return ret; 8267077148fSMark Brown val |= (regval & regwmask) << (regwshift*(regcount-i-1)); 8277077148fSMark Brown } 8287077148fSMark Brown val &= mask; 8297077148fSMark Brown if (min < 0 && val > max) 8307077148fSMark Brown val |= ~mask; 8317077148fSMark Brown if (invert) 8327077148fSMark Brown val = max - val; 8337077148fSMark Brown ucontrol->value.integer.value[0] = val; 8347077148fSMark Brown 8357077148fSMark Brown return 0; 8367077148fSMark Brown } 8377077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx); 8387077148fSMark Brown 8397077148fSMark Brown /** 8407077148fSMark Brown * snd_soc_put_xr_sx - signed multi register get callback 8417077148fSMark Brown * @kcontrol: mreg control 8427077148fSMark Brown * @ucontrol: control element information 8437077148fSMark Brown * 8447077148fSMark Brown * Callback to set the value of a control that can span 8457077148fSMark Brown * multiple codec registers which together forms a single 8467077148fSMark Brown * signed value in a MSB/LSB manner. The control supports 8477077148fSMark Brown * specifying total no of bits used to allow for bitfields 8487077148fSMark Brown * across the multiple codec registers. 8497077148fSMark Brown * 8507077148fSMark Brown * Returns 0 for success. 8517077148fSMark Brown */ 8527077148fSMark Brown int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, 8537077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 8547077148fSMark Brown { 8557077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 8567077148fSMark Brown struct soc_mreg_control *mc = 8577077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value; 8587077148fSMark Brown unsigned int regbase = mc->regbase; 8597077148fSMark Brown unsigned int regcount = mc->regcount; 8607077148fSMark Brown unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; 8617077148fSMark Brown unsigned int regwmask = (1<<regwshift)-1; 8627077148fSMark Brown unsigned int invert = mc->invert; 8637077148fSMark Brown unsigned long mask = (1UL<<mc->nbits)-1; 8647077148fSMark Brown long max = mc->max; 8657077148fSMark Brown long val = ucontrol->value.integer.value[0]; 8667077148fSMark Brown unsigned int i, regval, regmask; 8677077148fSMark Brown int err; 8687077148fSMark Brown 8697077148fSMark Brown if (invert) 8707077148fSMark Brown val = max - val; 8717077148fSMark Brown val &= mask; 8727077148fSMark Brown for (i = 0; i < regcount; i++) { 8737077148fSMark Brown regval = (val >> (regwshift*(regcount-i-1))) & regwmask; 8747077148fSMark Brown regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; 8757077148fSMark Brown err = snd_soc_component_update_bits(component, regbase+i, 8767077148fSMark Brown regmask, regval); 8777077148fSMark Brown if (err < 0) 8787077148fSMark Brown return err; 8797077148fSMark Brown } 8807077148fSMark Brown 8817077148fSMark Brown return 0; 8827077148fSMark Brown } 8837077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx); 8847077148fSMark Brown 8857077148fSMark Brown /** 8867077148fSMark Brown * snd_soc_get_strobe - strobe get callback 8877077148fSMark Brown * @kcontrol: mixer control 8887077148fSMark Brown * @ucontrol: control element information 8897077148fSMark Brown * 8907077148fSMark Brown * Callback get the value of a strobe mixer control. 8917077148fSMark Brown * 8927077148fSMark Brown * Returns 0 for success. 8937077148fSMark Brown */ 8947077148fSMark Brown int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, 8957077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 8967077148fSMark Brown { 8977077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 8987077148fSMark Brown struct soc_mixer_control *mc = 8997077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 9007077148fSMark Brown unsigned int reg = mc->reg; 9017077148fSMark Brown unsigned int shift = mc->shift; 9027077148fSMark Brown unsigned int mask = 1 << shift; 9037077148fSMark Brown unsigned int invert = mc->invert != 0; 9047077148fSMark Brown unsigned int val; 9057077148fSMark Brown int ret; 9067077148fSMark Brown 9077077148fSMark Brown ret = snd_soc_component_read(component, reg, &val); 9087077148fSMark Brown if (ret) 9097077148fSMark Brown return ret; 9107077148fSMark Brown 9117077148fSMark Brown val &= mask; 9127077148fSMark Brown 9137077148fSMark Brown if (shift != 0 && val != 0) 9147077148fSMark Brown val = val >> shift; 9157077148fSMark Brown ucontrol->value.enumerated.item[0] = val ^ invert; 9167077148fSMark Brown 9177077148fSMark Brown return 0; 9187077148fSMark Brown } 9197077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_strobe); 9207077148fSMark Brown 9217077148fSMark Brown /** 9227077148fSMark Brown * snd_soc_put_strobe - strobe put callback 9237077148fSMark Brown * @kcontrol: mixer control 9247077148fSMark Brown * @ucontrol: control element information 9257077148fSMark Brown * 9267077148fSMark Brown * Callback strobe a register bit to high then low (or the inverse) 9277077148fSMark Brown * in one pass of a single mixer enum control. 9287077148fSMark Brown * 9297077148fSMark Brown * Returns 1 for success. 9307077148fSMark Brown */ 9317077148fSMark Brown int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, 9327077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 9337077148fSMark Brown { 9347077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 9357077148fSMark Brown struct soc_mixer_control *mc = 9367077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 9377077148fSMark Brown unsigned int reg = mc->reg; 9387077148fSMark Brown unsigned int shift = mc->shift; 9397077148fSMark Brown unsigned int mask = 1 << shift; 9407077148fSMark Brown unsigned int invert = mc->invert != 0; 9417077148fSMark Brown unsigned int strobe = ucontrol->value.enumerated.item[0] != 0; 9427077148fSMark Brown unsigned int val1 = (strobe ^ invert) ? mask : 0; 9437077148fSMark Brown unsigned int val2 = (strobe ^ invert) ? 0 : mask; 9447077148fSMark Brown int err; 9457077148fSMark Brown 9467077148fSMark Brown err = snd_soc_component_update_bits(component, reg, mask, val1); 9477077148fSMark Brown if (err < 0) 9487077148fSMark Brown return err; 9497077148fSMark Brown 9507077148fSMark Brown return snd_soc_component_update_bits(component, reg, mask, val2); 9517077148fSMark Brown } 9527077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_strobe); 953