14eef5a90SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0+ 24eef5a90SKuninori Morimoto // 34eef5a90SKuninori Morimoto // soc-ops.c -- Generic ASoC operations 44eef5a90SKuninori Morimoto // 54eef5a90SKuninori Morimoto // Copyright 2005 Wolfson Microelectronics PLC. 64eef5a90SKuninori Morimoto // Copyright 2005 Openedhand Ltd. 74eef5a90SKuninori Morimoto // Copyright (C) 2010 Slimlogic Ltd. 84eef5a90SKuninori Morimoto // Copyright (C) 2010 Texas Instruments Inc. 94eef5a90SKuninori Morimoto // 104eef5a90SKuninori Morimoto // Author: Liam Girdwood <lrg@slimlogic.co.uk> 114eef5a90SKuninori Morimoto // with code, comments and ideas from :- 124eef5a90SKuninori Morimoto // Richard Purdie <richard@openedhand.com> 137077148fSMark Brown 147077148fSMark Brown #include <linux/module.h> 157077148fSMark Brown #include <linux/moduleparam.h> 167077148fSMark Brown #include <linux/init.h> 177077148fSMark Brown #include <linux/delay.h> 187077148fSMark Brown #include <linux/pm.h> 197077148fSMark Brown #include <linux/bitops.h> 207077148fSMark Brown #include <linux/ctype.h> 217077148fSMark Brown #include <linux/slab.h> 227077148fSMark Brown #include <sound/core.h> 237077148fSMark Brown #include <sound/jack.h> 247077148fSMark Brown #include <sound/pcm.h> 257077148fSMark Brown #include <sound/pcm_params.h> 267077148fSMark Brown #include <sound/soc.h> 277077148fSMark Brown #include <sound/soc-dpcm.h> 287077148fSMark Brown #include <sound/initval.h> 297077148fSMark Brown 307077148fSMark Brown /** 317077148fSMark Brown * snd_soc_info_enum_double - enumerated double mixer info callback 327077148fSMark Brown * @kcontrol: mixer control 337077148fSMark Brown * @uinfo: control element information 347077148fSMark Brown * 357077148fSMark Brown * Callback to provide information about a double enumerated 367077148fSMark Brown * mixer control. 377077148fSMark Brown * 387077148fSMark Brown * Returns 0 for success. 397077148fSMark Brown */ 407077148fSMark Brown int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, 417077148fSMark Brown struct snd_ctl_elem_info *uinfo) 427077148fSMark Brown { 437077148fSMark Brown struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 447077148fSMark Brown 457077148fSMark Brown return snd_ctl_enum_info(uinfo, e->shift_l == e->shift_r ? 1 : 2, 467077148fSMark Brown e->items, e->texts); 477077148fSMark Brown } 487077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_enum_double); 497077148fSMark Brown 507077148fSMark Brown /** 517077148fSMark Brown * snd_soc_get_enum_double - enumerated double mixer get callback 527077148fSMark Brown * @kcontrol: mixer control 537077148fSMark Brown * @ucontrol: control element information 547077148fSMark Brown * 557077148fSMark Brown * Callback to get the value of a double enumerated mixer. 567077148fSMark Brown * 577077148fSMark Brown * Returns 0 for success. 587077148fSMark Brown */ 597077148fSMark Brown int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, 607077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 617077148fSMark Brown { 627077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 637077148fSMark Brown struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 647077148fSMark Brown unsigned int val, item; 657077148fSMark Brown unsigned int reg_val; 667077148fSMark Brown 67cf6e26c7SKuninori Morimoto reg_val = snd_soc_component_read(component, e->reg); 687077148fSMark Brown val = (reg_val >> e->shift_l) & e->mask; 697077148fSMark Brown item = snd_soc_enum_val_to_item(e, val); 707077148fSMark Brown ucontrol->value.enumerated.item[0] = item; 717077148fSMark Brown if (e->shift_l != e->shift_r) { 72189f06c0SJaswinder Jassal val = (reg_val >> e->shift_r) & e->mask; 737077148fSMark Brown item = snd_soc_enum_val_to_item(e, val); 747077148fSMark Brown ucontrol->value.enumerated.item[1] = item; 757077148fSMark Brown } 767077148fSMark Brown 777077148fSMark Brown return 0; 787077148fSMark Brown } 797077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_enum_double); 807077148fSMark Brown 817077148fSMark Brown /** 827077148fSMark Brown * snd_soc_put_enum_double - enumerated double mixer put callback 837077148fSMark Brown * @kcontrol: mixer control 847077148fSMark Brown * @ucontrol: control element information 857077148fSMark Brown * 867077148fSMark Brown * Callback to set the value of a double enumerated mixer. 877077148fSMark Brown * 887077148fSMark Brown * Returns 0 for success. 897077148fSMark Brown */ 907077148fSMark Brown int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, 917077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 927077148fSMark Brown { 937077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 947077148fSMark Brown struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 957077148fSMark Brown unsigned int *item = ucontrol->value.enumerated.item; 967077148fSMark Brown unsigned int val; 977077148fSMark Brown unsigned int mask; 987077148fSMark Brown 997077148fSMark Brown if (item[0] >= e->items) 1007077148fSMark Brown return -EINVAL; 1017077148fSMark Brown val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; 1027077148fSMark Brown mask = e->mask << e->shift_l; 1037077148fSMark Brown if (e->shift_l != e->shift_r) { 1047077148fSMark Brown if (item[1] >= e->items) 1057077148fSMark Brown return -EINVAL; 1067077148fSMark Brown val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; 1077077148fSMark Brown mask |= e->mask << e->shift_r; 1087077148fSMark Brown } 1097077148fSMark Brown 1107077148fSMark Brown return snd_soc_component_update_bits(component, e->reg, mask, val); 1117077148fSMark Brown } 1127077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); 1137077148fSMark Brown 1147077148fSMark Brown /** 1158abab35fSCharles Keepax * snd_soc_read_signed - Read a codec register and interpret as signed value 1167077148fSMark Brown * @component: component 1177077148fSMark Brown * @reg: Register to read 1187077148fSMark Brown * @mask: Mask to use after shifting the register value 1197077148fSMark Brown * @shift: Right shift of register value 1207077148fSMark Brown * @sign_bit: Bit that describes if a number is negative or not. 1217077148fSMark Brown * @signed_val: Pointer to where the read value should be stored 1227077148fSMark Brown * 1237077148fSMark Brown * This functions reads a codec register. The register value is shifted right 1247077148fSMark Brown * by 'shift' bits and masked with the given 'mask'. Afterwards it translates 1257077148fSMark Brown * the given registervalue into a signed integer if sign_bit is non-zero. 1267077148fSMark Brown * 1277077148fSMark Brown * Returns 0 on sucess, otherwise an error value 1287077148fSMark Brown */ 1297077148fSMark Brown static int snd_soc_read_signed(struct snd_soc_component *component, 1307077148fSMark Brown unsigned int reg, unsigned int mask, unsigned int shift, 1317077148fSMark Brown unsigned int sign_bit, int *signed_val) 1327077148fSMark Brown { 1337077148fSMark Brown int ret; 1347077148fSMark Brown unsigned int val; 1357077148fSMark Brown 136cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, reg); 1377077148fSMark Brown val = (val >> shift) & mask; 1387077148fSMark Brown 1397077148fSMark Brown if (!sign_bit) { 1407077148fSMark Brown *signed_val = val; 1417077148fSMark Brown return 0; 1427077148fSMark Brown } 1437077148fSMark Brown 1447077148fSMark Brown /* non-negative number */ 1457077148fSMark Brown if (!(val & BIT(sign_bit))) { 1467077148fSMark Brown *signed_val = val; 1477077148fSMark Brown return 0; 1487077148fSMark Brown } 1497077148fSMark Brown 1507077148fSMark Brown ret = val; 1517077148fSMark Brown 1527077148fSMark Brown /* 1537077148fSMark Brown * The register most probably does not contain a full-sized int. 1547077148fSMark Brown * Instead we have an arbitrary number of bits in a signed 1557077148fSMark Brown * representation which has to be translated into a full-sized int. 1567077148fSMark Brown * This is done by filling up all bits above the sign-bit. 1577077148fSMark Brown */ 1587077148fSMark Brown ret |= ~((int)(BIT(sign_bit) - 1)); 1597077148fSMark Brown 1607077148fSMark Brown *signed_val = ret; 1617077148fSMark Brown 1627077148fSMark Brown return 0; 1637077148fSMark Brown } 1647077148fSMark Brown 1657077148fSMark Brown /** 1667077148fSMark Brown * snd_soc_info_volsw - single mixer info callback 1677077148fSMark Brown * @kcontrol: mixer control 1687077148fSMark Brown * @uinfo: control element information 1697077148fSMark Brown * 1707077148fSMark Brown * Callback to provide information about a single mixer control, or a double 1717077148fSMark Brown * mixer control that spans 2 registers. 1727077148fSMark Brown * 1737077148fSMark Brown * Returns 0 for success. 1747077148fSMark Brown */ 1757077148fSMark Brown int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, 1767077148fSMark Brown struct snd_ctl_elem_info *uinfo) 1777077148fSMark Brown { 1787077148fSMark Brown struct soc_mixer_control *mc = 1797077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 1807077148fSMark Brown int platform_max; 1817077148fSMark Brown 1827077148fSMark Brown if (!mc->platform_max) 1837077148fSMark Brown mc->platform_max = mc->max; 1847077148fSMark Brown platform_max = mc->platform_max; 1857077148fSMark Brown 1867077148fSMark Brown if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume")) 1877077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1887077148fSMark Brown else 1897077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 1907077148fSMark Brown 1917077148fSMark Brown uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; 1927077148fSMark Brown uinfo->value.integer.min = 0; 1937077148fSMark Brown uinfo->value.integer.max = platform_max - mc->min; 1947077148fSMark Brown return 0; 1957077148fSMark Brown } 1967077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw); 1977077148fSMark Brown 1987077148fSMark Brown /** 19934198710SCharles Keepax * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls 20034198710SCharles Keepax * @kcontrol: mixer control 20134198710SCharles Keepax * @uinfo: control element information 20234198710SCharles Keepax * 20334198710SCharles Keepax * Callback to provide information about a single mixer control, or a double 20434198710SCharles Keepax * mixer control that spans 2 registers of the SX TLV type. SX TLV controls 20534198710SCharles Keepax * have a range that represents both positive and negative values either side 20634198710SCharles Keepax * of zero but without a sign bit. 20734198710SCharles Keepax * 20834198710SCharles Keepax * Returns 0 for success. 20934198710SCharles Keepax */ 21034198710SCharles Keepax int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol, 21134198710SCharles Keepax struct snd_ctl_elem_info *uinfo) 21234198710SCharles Keepax { 21334198710SCharles Keepax struct soc_mixer_control *mc = 21434198710SCharles Keepax (struct soc_mixer_control *)kcontrol->private_value; 21534198710SCharles Keepax 21634198710SCharles Keepax snd_soc_info_volsw(kcontrol, uinfo); 21734198710SCharles Keepax /* Max represents the number of levels in an SX control not the 21834198710SCharles Keepax * maximum value, so add the minimum value back on 21934198710SCharles Keepax */ 22034198710SCharles Keepax uinfo->value.integer.max += mc->min; 22134198710SCharles Keepax 22234198710SCharles Keepax return 0; 22334198710SCharles Keepax } 22434198710SCharles Keepax EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx); 22534198710SCharles Keepax 22634198710SCharles Keepax /** 2277077148fSMark Brown * snd_soc_get_volsw - single mixer get callback 2287077148fSMark Brown * @kcontrol: mixer control 2297077148fSMark Brown * @ucontrol: control element information 2307077148fSMark Brown * 2317077148fSMark Brown * Callback to get the value of a single mixer control, or a double mixer 2327077148fSMark Brown * control that spans 2 registers. 2337077148fSMark Brown * 2347077148fSMark Brown * Returns 0 for success. 2357077148fSMark Brown */ 2367077148fSMark Brown int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, 2377077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 2387077148fSMark Brown { 2397077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 2407077148fSMark Brown struct soc_mixer_control *mc = 2417077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 2427077148fSMark Brown unsigned int reg = mc->reg; 2437077148fSMark Brown unsigned int reg2 = mc->rreg; 2447077148fSMark Brown unsigned int shift = mc->shift; 2457077148fSMark Brown unsigned int rshift = mc->rshift; 2467077148fSMark Brown int max = mc->max; 2477077148fSMark Brown int min = mc->min; 2487077148fSMark Brown int sign_bit = mc->sign_bit; 2497077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 2507077148fSMark Brown unsigned int invert = mc->invert; 2517077148fSMark Brown int val; 2527077148fSMark Brown int ret; 2537077148fSMark Brown 2547077148fSMark Brown if (sign_bit) 2557077148fSMark Brown mask = BIT(sign_bit + 1) - 1; 2567077148fSMark Brown 2577077148fSMark Brown ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); 2587077148fSMark Brown if (ret) 2597077148fSMark Brown return ret; 2607077148fSMark Brown 2617077148fSMark Brown ucontrol->value.integer.value[0] = val - min; 2627077148fSMark Brown if (invert) 2637077148fSMark Brown ucontrol->value.integer.value[0] = 2647077148fSMark Brown max - ucontrol->value.integer.value[0]; 2657077148fSMark Brown 2667077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 2677077148fSMark Brown if (reg == reg2) 2687077148fSMark Brown ret = snd_soc_read_signed(component, reg, mask, rshift, 2697077148fSMark Brown sign_bit, &val); 2707077148fSMark Brown else 2717077148fSMark Brown ret = snd_soc_read_signed(component, reg2, mask, shift, 2727077148fSMark Brown sign_bit, &val); 2737077148fSMark Brown if (ret) 2747077148fSMark Brown return ret; 2757077148fSMark Brown 2767077148fSMark Brown ucontrol->value.integer.value[1] = val - min; 2777077148fSMark Brown if (invert) 2787077148fSMark Brown ucontrol->value.integer.value[1] = 2797077148fSMark Brown max - ucontrol->value.integer.value[1]; 2807077148fSMark Brown } 2817077148fSMark Brown 2827077148fSMark Brown return 0; 2837077148fSMark Brown } 2847077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw); 2857077148fSMark Brown 2867077148fSMark Brown /** 2877077148fSMark Brown * snd_soc_put_volsw - single mixer put callback 2887077148fSMark Brown * @kcontrol: mixer control 2897077148fSMark Brown * @ucontrol: control element information 2907077148fSMark Brown * 2917077148fSMark Brown * Callback to set the value of a single mixer control, or a double mixer 2927077148fSMark Brown * control that spans 2 registers. 2937077148fSMark Brown * 2947077148fSMark Brown * Returns 0 for success. 2957077148fSMark Brown */ 2967077148fSMark Brown int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, 2977077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 2987077148fSMark Brown { 2997077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 3007077148fSMark Brown struct soc_mixer_control *mc = 3017077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 3027077148fSMark Brown unsigned int reg = mc->reg; 3037077148fSMark Brown unsigned int reg2 = mc->rreg; 3047077148fSMark Brown unsigned int shift = mc->shift; 3057077148fSMark Brown unsigned int rshift = mc->rshift; 3067077148fSMark Brown int max = mc->max; 3077077148fSMark Brown int min = mc->min; 3087077148fSMark Brown unsigned int sign_bit = mc->sign_bit; 3097077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 3107077148fSMark Brown unsigned int invert = mc->invert; 311564778d7SMark Brown int err, ret; 3127077148fSMark Brown bool type_2r = false; 3137077148fSMark Brown unsigned int val2 = 0; 3147077148fSMark Brown unsigned int val, val_mask; 3157077148fSMark Brown 3167077148fSMark Brown if (sign_bit) 3177077148fSMark Brown mask = BIT(sign_bit + 1) - 1; 3187077148fSMark Brown 3191601033dSMark Brown if (ucontrol->value.integer.value[0] < 0) 3201601033dSMark Brown return -EINVAL; 321817f7c93SMark Brown val = ucontrol->value.integer.value[0]; 322817f7c93SMark Brown if (mc->platform_max && val > mc->platform_max) 323817f7c93SMark Brown return -EINVAL; 324817f7c93SMark Brown if (val > max - min) 325817f7c93SMark Brown return -EINVAL; 326817f7c93SMark Brown val = (val + min) & mask; 3277077148fSMark Brown if (invert) 3287077148fSMark Brown val = max - val; 3297077148fSMark Brown val_mask = mask << shift; 3307077148fSMark Brown val = val << shift; 3317077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 3321601033dSMark Brown if (ucontrol->value.integer.value[1] < 0) 3331601033dSMark Brown return -EINVAL; 334817f7c93SMark Brown val2 = ucontrol->value.integer.value[1]; 335817f7c93SMark Brown if (mc->platform_max && val2 > mc->platform_max) 336817f7c93SMark Brown return -EINVAL; 337817f7c93SMark Brown if (val2 > max - min) 338817f7c93SMark Brown return -EINVAL; 339817f7c93SMark Brown val2 = (val2 + min) & mask; 3407077148fSMark Brown if (invert) 3417077148fSMark Brown val2 = max - val2; 3427077148fSMark Brown if (reg == reg2) { 3437077148fSMark Brown val_mask |= mask << rshift; 3447077148fSMark Brown val |= val2 << rshift; 3457077148fSMark Brown } else { 3467077148fSMark Brown val2 = val2 << shift; 3477077148fSMark Brown type_2r = true; 3487077148fSMark Brown } 3497077148fSMark Brown } 3507077148fSMark Brown err = snd_soc_component_update_bits(component, reg, val_mask, val); 3517077148fSMark Brown if (err < 0) 3527077148fSMark Brown return err; 353564778d7SMark Brown ret = err; 3547077148fSMark Brown 355564778d7SMark Brown if (type_2r) { 3567077148fSMark Brown err = snd_soc_component_update_bits(component, reg2, val_mask, 3577077148fSMark Brown val2); 358564778d7SMark Brown /* Don't discard any error code or drop change flag */ 359564778d7SMark Brown if (ret == 0 || err < 0) { 360564778d7SMark Brown ret = err; 361564778d7SMark Brown } 362564778d7SMark Brown } 3637077148fSMark Brown 364564778d7SMark Brown return ret; 3657077148fSMark Brown } 3667077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw); 3677077148fSMark Brown 3687077148fSMark Brown /** 3697077148fSMark Brown * snd_soc_get_volsw_sx - single mixer get callback 3707077148fSMark Brown * @kcontrol: mixer control 3717077148fSMark Brown * @ucontrol: control element information 3727077148fSMark Brown * 3737077148fSMark Brown * Callback to get the value of a single mixer control, or a double mixer 3747077148fSMark Brown * control that spans 2 registers. 3757077148fSMark Brown * 3767077148fSMark Brown * Returns 0 for success. 3777077148fSMark Brown */ 3787077148fSMark Brown int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, 3797077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 3807077148fSMark Brown { 3817077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 3827077148fSMark Brown struct soc_mixer_control *mc = 3837077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 3847077148fSMark Brown unsigned int reg = mc->reg; 3857077148fSMark Brown unsigned int reg2 = mc->rreg; 3867077148fSMark Brown unsigned int shift = mc->shift; 3877077148fSMark Brown unsigned int rshift = mc->rshift; 3887077148fSMark Brown int max = mc->max; 3897077148fSMark Brown int min = mc->min; 390ae7d1247SRohit kumar unsigned int mask = (1U << (fls(min + max) - 1)) - 1; 3917077148fSMark Brown unsigned int val; 3927077148fSMark Brown 393cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, reg); 3947077148fSMark Brown ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; 3957077148fSMark Brown 3967077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 397cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, reg2); 3987077148fSMark Brown val = ((val >> rshift) - min) & mask; 3997077148fSMark Brown ucontrol->value.integer.value[1] = val; 4007077148fSMark Brown } 4017077148fSMark Brown 4027077148fSMark Brown return 0; 4037077148fSMark Brown } 4047077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx); 4057077148fSMark Brown 4067077148fSMark Brown /** 4077077148fSMark Brown * snd_soc_put_volsw_sx - double mixer set callback 4087077148fSMark Brown * @kcontrol: mixer control 4099a11ef7fSRandy Dunlap * @ucontrol: control element information 4107077148fSMark Brown * 4117077148fSMark Brown * Callback to set the value of a double mixer control that spans 2 registers. 4127077148fSMark Brown * 4137077148fSMark Brown * Returns 0 for success. 4147077148fSMark Brown */ 4157077148fSMark Brown int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, 4167077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 4177077148fSMark Brown { 4187077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 4197077148fSMark Brown struct soc_mixer_control *mc = 4207077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 4217077148fSMark Brown 4227077148fSMark Brown unsigned int reg = mc->reg; 4237077148fSMark Brown unsigned int reg2 = mc->rreg; 4247077148fSMark Brown unsigned int shift = mc->shift; 4257077148fSMark Brown unsigned int rshift = mc->rshift; 4267077148fSMark Brown int max = mc->max; 4277077148fSMark Brown int min = mc->min; 428ae7d1247SRohit kumar unsigned int mask = (1U << (fls(min + max) - 1)) - 1; 4297077148fSMark Brown int err = 0; 430*7f3d90a3SMark Brown int ret; 43158f42dfdSKuninori Morimoto unsigned int val, val_mask; 4327077148fSMark Brown 4331601033dSMark Brown if (ucontrol->value.integer.value[0] < 0) 4341601033dSMark Brown return -EINVAL; 4354f1e50d6SMark Brown val = ucontrol->value.integer.value[0]; 4364f1e50d6SMark Brown if (mc->platform_max && val > mc->platform_max) 4374f1e50d6SMark Brown return -EINVAL; 4384f1e50d6SMark Brown if (val > max - min) 4394f1e50d6SMark Brown return -EINVAL; 4407077148fSMark Brown val_mask = mask << shift; 4414f1e50d6SMark Brown val = (val + min) & mask; 4427077148fSMark Brown val = val << shift; 4437077148fSMark Brown 4447077148fSMark Brown err = snd_soc_component_update_bits(component, reg, val_mask, val); 4457077148fSMark Brown if (err < 0) 4467077148fSMark Brown return err; 447*7f3d90a3SMark Brown ret = err; 4487077148fSMark Brown 4497077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 45058f42dfdSKuninori Morimoto unsigned int val2; 45158f42dfdSKuninori Morimoto 4527077148fSMark Brown val_mask = mask << rshift; 4537077148fSMark Brown val2 = (ucontrol->value.integer.value[1] + min) & mask; 4547077148fSMark Brown val2 = val2 << rshift; 4557077148fSMark Brown 4567077148fSMark Brown err = snd_soc_component_update_bits(component, reg2, val_mask, 4577077148fSMark Brown val2); 458*7f3d90a3SMark Brown 459*7f3d90a3SMark Brown /* Don't discard any error code or drop change flag */ 460*7f3d90a3SMark Brown if (ret == 0 || err < 0) { 461*7f3d90a3SMark Brown ret = err; 462*7f3d90a3SMark Brown } 4637077148fSMark Brown } 4647077148fSMark Brown return err; 4657077148fSMark Brown } 4667077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); 4677077148fSMark Brown 4687077148fSMark Brown /** 4697077148fSMark Brown * snd_soc_info_volsw_range - single mixer info callback with range. 4707077148fSMark Brown * @kcontrol: mixer control 4717077148fSMark Brown * @uinfo: control element information 4727077148fSMark Brown * 4737077148fSMark Brown * Callback to provide information, within a range, about a single 4747077148fSMark Brown * mixer control. 4757077148fSMark Brown * 4767077148fSMark Brown * returns 0 for success. 4777077148fSMark Brown */ 4787077148fSMark Brown int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, 4797077148fSMark Brown struct snd_ctl_elem_info *uinfo) 4807077148fSMark Brown { 4817077148fSMark Brown struct soc_mixer_control *mc = 4827077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 4837077148fSMark Brown int platform_max; 4847077148fSMark Brown int min = mc->min; 4857077148fSMark Brown 4867077148fSMark Brown if (!mc->platform_max) 4877077148fSMark Brown mc->platform_max = mc->max; 4887077148fSMark Brown platform_max = mc->platform_max; 4897077148fSMark Brown 4907077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 4917077148fSMark Brown uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; 4927077148fSMark Brown uinfo->value.integer.min = 0; 4937077148fSMark Brown uinfo->value.integer.max = platform_max - min; 4947077148fSMark Brown 4957077148fSMark Brown return 0; 4967077148fSMark Brown } 4977077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); 4987077148fSMark Brown 4997077148fSMark Brown /** 5007077148fSMark Brown * snd_soc_put_volsw_range - single mixer put value callback with range. 5017077148fSMark Brown * @kcontrol: mixer control 5027077148fSMark Brown * @ucontrol: control element information 5037077148fSMark Brown * 5047077148fSMark Brown * Callback to set the value, within a range, for a single mixer control. 5057077148fSMark Brown * 5067077148fSMark Brown * Returns 0 for success. 5077077148fSMark Brown */ 5087077148fSMark Brown int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, 5097077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 5107077148fSMark Brown { 5117077148fSMark Brown struct soc_mixer_control *mc = 5127077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 5137077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 5147077148fSMark Brown unsigned int reg = mc->reg; 5157077148fSMark Brown unsigned int rreg = mc->rreg; 5167077148fSMark Brown unsigned int shift = mc->shift; 5177077148fSMark Brown int min = mc->min; 5187077148fSMark Brown int max = mc->max; 5197077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 5207077148fSMark Brown unsigned int invert = mc->invert; 5217077148fSMark Brown unsigned int val, val_mask; 5227077148fSMark Brown int ret; 5237077148fSMark Brown 5247077148fSMark Brown if (invert) 5257077148fSMark Brown val = (max - ucontrol->value.integer.value[0]) & mask; 5267077148fSMark Brown else 5277077148fSMark Brown val = ((ucontrol->value.integer.value[0] + min) & mask); 5287077148fSMark Brown val_mask = mask << shift; 5297077148fSMark Brown val = val << shift; 5307077148fSMark Brown 5317077148fSMark Brown ret = snd_soc_component_update_bits(component, reg, val_mask, val); 5327077148fSMark Brown if (ret < 0) 5337077148fSMark Brown return ret; 5347077148fSMark Brown 5357077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 5367077148fSMark Brown if (invert) 5377077148fSMark Brown val = (max - ucontrol->value.integer.value[1]) & mask; 5387077148fSMark Brown else 5397077148fSMark Brown val = ((ucontrol->value.integer.value[1] + min) & mask); 5407077148fSMark Brown val_mask = mask << shift; 5417077148fSMark Brown val = val << shift; 5427077148fSMark Brown 5437077148fSMark Brown ret = snd_soc_component_update_bits(component, rreg, val_mask, 5447077148fSMark Brown val); 5457077148fSMark Brown } 5467077148fSMark Brown 5477077148fSMark Brown return ret; 5487077148fSMark Brown } 5497077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); 5507077148fSMark Brown 5517077148fSMark Brown /** 5527077148fSMark Brown * snd_soc_get_volsw_range - single mixer get callback with range 5537077148fSMark Brown * @kcontrol: mixer control 5547077148fSMark Brown * @ucontrol: control element information 5557077148fSMark Brown * 5567077148fSMark Brown * Callback to get the value, within a range, of a single mixer control. 5577077148fSMark Brown * 5587077148fSMark Brown * Returns 0 for success. 5597077148fSMark Brown */ 5607077148fSMark Brown int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, 5617077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 5627077148fSMark Brown { 5637077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 5647077148fSMark Brown struct soc_mixer_control *mc = 5657077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 5667077148fSMark Brown unsigned int reg = mc->reg; 5677077148fSMark Brown unsigned int rreg = mc->rreg; 5687077148fSMark Brown unsigned int shift = mc->shift; 5697077148fSMark Brown int min = mc->min; 5707077148fSMark Brown int max = mc->max; 5717077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 5727077148fSMark Brown unsigned int invert = mc->invert; 5737077148fSMark Brown unsigned int val; 5747077148fSMark Brown 575cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, reg); 5767077148fSMark Brown ucontrol->value.integer.value[0] = (val >> shift) & mask; 5777077148fSMark Brown if (invert) 5787077148fSMark Brown ucontrol->value.integer.value[0] = 5797077148fSMark Brown max - ucontrol->value.integer.value[0]; 5807077148fSMark Brown else 5817077148fSMark Brown ucontrol->value.integer.value[0] = 5827077148fSMark Brown ucontrol->value.integer.value[0] - min; 5837077148fSMark Brown 5847077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 585cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, rreg); 5867077148fSMark Brown ucontrol->value.integer.value[1] = (val >> shift) & mask; 5877077148fSMark Brown if (invert) 5887077148fSMark Brown ucontrol->value.integer.value[1] = 5897077148fSMark Brown max - ucontrol->value.integer.value[1]; 5907077148fSMark Brown else 5917077148fSMark Brown ucontrol->value.integer.value[1] = 5927077148fSMark Brown ucontrol->value.integer.value[1] - min; 5937077148fSMark Brown } 5947077148fSMark Brown 5957077148fSMark Brown return 0; 5967077148fSMark Brown } 5977077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); 5987077148fSMark Brown 5997077148fSMark Brown /** 6007077148fSMark Brown * snd_soc_limit_volume - Set new limit to an existing volume control. 6017077148fSMark Brown * 60226d9ca34SLars-Peter Clausen * @card: where to look for the control 6037077148fSMark Brown * @name: Name of the control 6047077148fSMark Brown * @max: new maximum limit 6057077148fSMark Brown * 6067077148fSMark Brown * Return 0 for success, else error. 6077077148fSMark Brown */ 60826d9ca34SLars-Peter Clausen int snd_soc_limit_volume(struct snd_soc_card *card, 6097077148fSMark Brown const char *name, int max) 6107077148fSMark Brown { 6117077148fSMark Brown struct snd_kcontrol *kctl; 6127077148fSMark Brown int ret = -EINVAL; 6137077148fSMark Brown 6147077148fSMark Brown /* Sanity check for name and max */ 6157077148fSMark Brown if (unlikely(!name || max <= 0)) 6167077148fSMark Brown return -EINVAL; 6177077148fSMark Brown 6180881ab6eSKuninori Morimoto kctl = snd_soc_card_get_kcontrol(card, name); 6190881ab6eSKuninori Morimoto if (kctl) { 620872040f7SKuninori Morimoto struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; 6217077148fSMark Brown if (max <= mc->max) { 6227077148fSMark Brown mc->platform_max = max; 6237077148fSMark Brown ret = 0; 6247077148fSMark Brown } 6257077148fSMark Brown } 6267077148fSMark Brown return ret; 6277077148fSMark Brown } 6287077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_limit_volume); 6297077148fSMark Brown 6307077148fSMark Brown int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, 6317077148fSMark Brown struct snd_ctl_elem_info *uinfo) 6327077148fSMark Brown { 6337077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 6347077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value; 6357077148fSMark Brown 6367077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 6377077148fSMark Brown uinfo->count = params->num_regs * component->val_bytes; 6387077148fSMark Brown 6397077148fSMark Brown return 0; 6407077148fSMark Brown } 6417077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info); 6427077148fSMark Brown 6437077148fSMark Brown int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, 6447077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 6457077148fSMark Brown { 6467077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 6477077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value; 6487077148fSMark Brown int ret; 6497077148fSMark Brown 6507077148fSMark Brown if (component->regmap) 6517077148fSMark Brown ret = regmap_raw_read(component->regmap, params->base, 6527077148fSMark Brown ucontrol->value.bytes.data, 6537077148fSMark Brown params->num_regs * component->val_bytes); 6547077148fSMark Brown else 6557077148fSMark Brown ret = -EINVAL; 6567077148fSMark Brown 6577077148fSMark Brown /* Hide any masked bytes to ensure consistent data reporting */ 6587077148fSMark Brown if (ret == 0 && params->mask) { 6597077148fSMark Brown switch (component->val_bytes) { 6607077148fSMark Brown case 1: 6617077148fSMark Brown ucontrol->value.bytes.data[0] &= ~params->mask; 6627077148fSMark Brown break; 6637077148fSMark Brown case 2: 6647077148fSMark Brown ((u16 *)(&ucontrol->value.bytes.data))[0] 6657077148fSMark Brown &= cpu_to_be16(~params->mask); 6667077148fSMark Brown break; 6677077148fSMark Brown case 4: 6687077148fSMark Brown ((u32 *)(&ucontrol->value.bytes.data))[0] 6697077148fSMark Brown &= cpu_to_be32(~params->mask); 6707077148fSMark Brown break; 6717077148fSMark Brown default: 6727077148fSMark Brown return -EINVAL; 6737077148fSMark Brown } 6747077148fSMark Brown } 6757077148fSMark Brown 6767077148fSMark Brown return ret; 6777077148fSMark Brown } 6787077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_get); 6797077148fSMark Brown 6807077148fSMark Brown int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, 6817077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 6827077148fSMark Brown { 6837077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 6847077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value; 6857077148fSMark Brown int ret, len; 6867077148fSMark Brown unsigned int val, mask; 6877077148fSMark Brown void *data; 6887077148fSMark Brown 6897077148fSMark Brown if (!component->regmap || !params->num_regs) 6907077148fSMark Brown return -EINVAL; 6917077148fSMark Brown 6927077148fSMark Brown len = params->num_regs * component->val_bytes; 6937077148fSMark Brown 6947077148fSMark Brown data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); 6957077148fSMark Brown if (!data) 6967077148fSMark Brown return -ENOMEM; 6977077148fSMark Brown 6987077148fSMark Brown /* 6997077148fSMark Brown * If we've got a mask then we need to preserve the register 7007077148fSMark Brown * bits. We shouldn't modify the incoming data so take a 7017077148fSMark Brown * copy. 7027077148fSMark Brown */ 7037077148fSMark Brown if (params->mask) { 7047077148fSMark Brown ret = regmap_read(component->regmap, params->base, &val); 7057077148fSMark Brown if (ret != 0) 7067077148fSMark Brown goto out; 7077077148fSMark Brown 7087077148fSMark Brown val &= params->mask; 7097077148fSMark Brown 7107077148fSMark Brown switch (component->val_bytes) { 7117077148fSMark Brown case 1: 7127077148fSMark Brown ((u8 *)data)[0] &= ~params->mask; 7137077148fSMark Brown ((u8 *)data)[0] |= val; 7147077148fSMark Brown break; 7157077148fSMark Brown case 2: 7167077148fSMark Brown mask = ~params->mask; 7177077148fSMark Brown ret = regmap_parse_val(component->regmap, 7187077148fSMark Brown &mask, &mask); 7197077148fSMark Brown if (ret != 0) 7207077148fSMark Brown goto out; 7217077148fSMark Brown 7227077148fSMark Brown ((u16 *)data)[0] &= mask; 7237077148fSMark Brown 7247077148fSMark Brown ret = regmap_parse_val(component->regmap, 7257077148fSMark Brown &val, &val); 7267077148fSMark Brown if (ret != 0) 7277077148fSMark Brown goto out; 7287077148fSMark Brown 7297077148fSMark Brown ((u16 *)data)[0] |= val; 7307077148fSMark Brown break; 7317077148fSMark Brown case 4: 7327077148fSMark Brown mask = ~params->mask; 7337077148fSMark Brown ret = regmap_parse_val(component->regmap, 7347077148fSMark Brown &mask, &mask); 7357077148fSMark Brown if (ret != 0) 7367077148fSMark Brown goto out; 7377077148fSMark Brown 7387077148fSMark Brown ((u32 *)data)[0] &= mask; 7397077148fSMark Brown 7407077148fSMark Brown ret = regmap_parse_val(component->regmap, 7417077148fSMark Brown &val, &val); 7427077148fSMark Brown if (ret != 0) 7437077148fSMark Brown goto out; 7447077148fSMark Brown 7457077148fSMark Brown ((u32 *)data)[0] |= val; 7467077148fSMark Brown break; 7477077148fSMark Brown default: 7487077148fSMark Brown ret = -EINVAL; 7497077148fSMark Brown goto out; 7507077148fSMark Brown } 7517077148fSMark Brown } 7527077148fSMark Brown 7537077148fSMark Brown ret = regmap_raw_write(component->regmap, params->base, 7547077148fSMark Brown data, len); 7557077148fSMark Brown 7567077148fSMark Brown out: 7577077148fSMark Brown kfree(data); 7587077148fSMark Brown 7597077148fSMark Brown return ret; 7607077148fSMark Brown } 7617077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_put); 7627077148fSMark Brown 7637077148fSMark Brown int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, 7647077148fSMark Brown struct snd_ctl_elem_info *ucontrol) 7657077148fSMark Brown { 7667077148fSMark Brown struct soc_bytes_ext *params = (void *)kcontrol->private_value; 7677077148fSMark Brown 7687077148fSMark Brown ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; 7697077148fSMark Brown ucontrol->count = params->max; 7707077148fSMark Brown 7717077148fSMark Brown return 0; 7727077148fSMark Brown } 7737077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); 7747077148fSMark Brown 7757077148fSMark Brown int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, 7767077148fSMark Brown unsigned int size, unsigned int __user *tlv) 7777077148fSMark Brown { 7787077148fSMark Brown struct soc_bytes_ext *params = (void *)kcontrol->private_value; 7797077148fSMark Brown unsigned int count = size < params->max ? size : params->max; 7807077148fSMark Brown int ret = -ENXIO; 7817077148fSMark Brown 7827077148fSMark Brown switch (op_flag) { 7837077148fSMark Brown case SNDRV_CTL_TLV_OP_READ: 7847077148fSMark Brown if (params->get) 785a1e5e7e9SMythri P K ret = params->get(kcontrol, tlv, count); 7867077148fSMark Brown break; 7877077148fSMark Brown case SNDRV_CTL_TLV_OP_WRITE: 7887077148fSMark Brown if (params->put) 789a1e5e7e9SMythri P K ret = params->put(kcontrol, tlv, count); 7907077148fSMark Brown break; 7917077148fSMark Brown } 7927077148fSMark Brown return ret; 7937077148fSMark Brown } 7947077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); 7957077148fSMark Brown 7967077148fSMark Brown /** 7977077148fSMark Brown * snd_soc_info_xr_sx - signed multi register info callback 7987077148fSMark Brown * @kcontrol: mreg control 7997077148fSMark Brown * @uinfo: control element information 8007077148fSMark Brown * 8017077148fSMark Brown * Callback to provide information of a control that can 8027077148fSMark Brown * span multiple codec registers which together 8037077148fSMark Brown * forms a single signed value in a MSB/LSB manner. 8047077148fSMark Brown * 8057077148fSMark Brown * Returns 0 for success. 8067077148fSMark Brown */ 8077077148fSMark Brown int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, 8087077148fSMark Brown struct snd_ctl_elem_info *uinfo) 8097077148fSMark Brown { 8107077148fSMark Brown struct soc_mreg_control *mc = 8117077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value; 8127077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 8137077148fSMark Brown uinfo->count = 1; 8147077148fSMark Brown uinfo->value.integer.min = mc->min; 8157077148fSMark Brown uinfo->value.integer.max = mc->max; 8167077148fSMark Brown 8177077148fSMark Brown return 0; 8187077148fSMark Brown } 8197077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx); 8207077148fSMark Brown 8217077148fSMark Brown /** 8227077148fSMark Brown * snd_soc_get_xr_sx - signed multi register get callback 8237077148fSMark Brown * @kcontrol: mreg control 8247077148fSMark Brown * @ucontrol: control element information 8257077148fSMark Brown * 8267077148fSMark Brown * Callback to get the value of a control that can span 8277077148fSMark Brown * multiple codec registers which together forms a single 8287077148fSMark Brown * signed value in a MSB/LSB manner. The control supports 8297077148fSMark Brown * specifying total no of bits used to allow for bitfields 8307077148fSMark Brown * across the multiple codec registers. 8317077148fSMark Brown * 8327077148fSMark Brown * Returns 0 for success. 8337077148fSMark Brown */ 8347077148fSMark Brown int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, 8357077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 8367077148fSMark Brown { 8377077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 8387077148fSMark Brown struct soc_mreg_control *mc = 8397077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value; 8407077148fSMark Brown unsigned int regbase = mc->regbase; 8417077148fSMark Brown unsigned int regcount = mc->regcount; 8427077148fSMark Brown unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; 8430ab07091S이경택 unsigned int regwmask = (1UL<<regwshift)-1; 8447077148fSMark Brown unsigned int invert = mc->invert; 8457077148fSMark Brown unsigned long mask = (1UL<<mc->nbits)-1; 8467077148fSMark Brown long min = mc->min; 8477077148fSMark Brown long max = mc->max; 8487077148fSMark Brown long val = 0; 8497077148fSMark Brown unsigned int i; 8507077148fSMark Brown 8517077148fSMark Brown for (i = 0; i < regcount; i++) { 852b1ebecb9SKuninori Morimoto unsigned int regval = snd_soc_component_read(component, regbase+i); 8537077148fSMark Brown val |= (regval & regwmask) << (regwshift*(regcount-i-1)); 8547077148fSMark Brown } 8557077148fSMark Brown val &= mask; 8567077148fSMark Brown if (min < 0 && val > max) 8577077148fSMark Brown val |= ~mask; 8587077148fSMark Brown if (invert) 8597077148fSMark Brown val = max - val; 8607077148fSMark Brown ucontrol->value.integer.value[0] = val; 8617077148fSMark Brown 8627077148fSMark Brown return 0; 8637077148fSMark Brown } 8647077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx); 8657077148fSMark Brown 8667077148fSMark Brown /** 8677077148fSMark Brown * snd_soc_put_xr_sx - signed multi register get callback 8687077148fSMark Brown * @kcontrol: mreg control 8697077148fSMark Brown * @ucontrol: control element information 8707077148fSMark Brown * 8717077148fSMark Brown * Callback to set the value of a control that can span 8727077148fSMark Brown * multiple codec registers which together forms a single 8737077148fSMark Brown * signed value in a MSB/LSB manner. The control supports 8747077148fSMark Brown * specifying total no of bits used to allow for bitfields 8757077148fSMark Brown * across the multiple codec registers. 8767077148fSMark Brown * 8777077148fSMark Brown * Returns 0 for success. 8787077148fSMark Brown */ 8797077148fSMark Brown int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, 8807077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 8817077148fSMark Brown { 8827077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 8837077148fSMark Brown struct soc_mreg_control *mc = 8847077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value; 8857077148fSMark Brown unsigned int regbase = mc->regbase; 8867077148fSMark Brown unsigned int regcount = mc->regcount; 8877077148fSMark Brown unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; 8880ab07091S이경택 unsigned int regwmask = (1UL<<regwshift)-1; 8897077148fSMark Brown unsigned int invert = mc->invert; 8907077148fSMark Brown unsigned long mask = (1UL<<mc->nbits)-1; 8917077148fSMark Brown long max = mc->max; 8927077148fSMark Brown long val = ucontrol->value.integer.value[0]; 893b285b510SKuninori Morimoto unsigned int i; 8947077148fSMark Brown 8954cf28e9aSMark Brown if (val < mc->min || val > mc->max) 8964cf28e9aSMark Brown return -EINVAL; 8977077148fSMark Brown if (invert) 8987077148fSMark Brown val = max - val; 8997077148fSMark Brown val &= mask; 9007077148fSMark Brown for (i = 0; i < regcount; i++) { 901b285b510SKuninori Morimoto unsigned int regval = (val >> (regwshift*(regcount-i-1))) & regwmask; 902b285b510SKuninori Morimoto unsigned int regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; 903b285b510SKuninori Morimoto int err = snd_soc_component_update_bits(component, regbase+i, 9047077148fSMark Brown regmask, regval); 9057077148fSMark Brown if (err < 0) 9067077148fSMark Brown return err; 9077077148fSMark Brown } 9087077148fSMark Brown 9097077148fSMark Brown return 0; 9107077148fSMark Brown } 9117077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_xr_sx); 9127077148fSMark Brown 9137077148fSMark Brown /** 9147077148fSMark Brown * snd_soc_get_strobe - strobe get callback 9157077148fSMark Brown * @kcontrol: mixer control 9167077148fSMark Brown * @ucontrol: control element information 9177077148fSMark Brown * 9187077148fSMark Brown * Callback get the value of a strobe mixer control. 9197077148fSMark Brown * 9207077148fSMark Brown * Returns 0 for success. 9217077148fSMark Brown */ 9227077148fSMark Brown int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, 9237077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 9247077148fSMark Brown { 9257077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 9267077148fSMark Brown struct soc_mixer_control *mc = 9277077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 9287077148fSMark Brown unsigned int reg = mc->reg; 9297077148fSMark Brown unsigned int shift = mc->shift; 9307077148fSMark Brown unsigned int mask = 1 << shift; 9317077148fSMark Brown unsigned int invert = mc->invert != 0; 9327077148fSMark Brown unsigned int val; 9337077148fSMark Brown 934cf6e26c7SKuninori Morimoto val = snd_soc_component_read(component, reg); 9357077148fSMark Brown val &= mask; 9367077148fSMark Brown 9377077148fSMark Brown if (shift != 0 && val != 0) 9387077148fSMark Brown val = val >> shift; 9397077148fSMark Brown ucontrol->value.enumerated.item[0] = val ^ invert; 9407077148fSMark Brown 9417077148fSMark Brown return 0; 9427077148fSMark Brown } 9437077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_strobe); 9447077148fSMark Brown 9457077148fSMark Brown /** 9467077148fSMark Brown * snd_soc_put_strobe - strobe put callback 9477077148fSMark Brown * @kcontrol: mixer control 9487077148fSMark Brown * @ucontrol: control element information 9497077148fSMark Brown * 9507077148fSMark Brown * Callback strobe a register bit to high then low (or the inverse) 9517077148fSMark Brown * in one pass of a single mixer enum control. 9527077148fSMark Brown * 9537077148fSMark Brown * Returns 1 for success. 9547077148fSMark Brown */ 9557077148fSMark Brown int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, 9567077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 9577077148fSMark Brown { 9587077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 9597077148fSMark Brown struct soc_mixer_control *mc = 9607077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 9617077148fSMark Brown unsigned int reg = mc->reg; 9627077148fSMark Brown unsigned int shift = mc->shift; 9637077148fSMark Brown unsigned int mask = 1 << shift; 9647077148fSMark Brown unsigned int invert = mc->invert != 0; 9657077148fSMark Brown unsigned int strobe = ucontrol->value.enumerated.item[0] != 0; 9667077148fSMark Brown unsigned int val1 = (strobe ^ invert) ? mask : 0; 9677077148fSMark Brown unsigned int val2 = (strobe ^ invert) ? 0 : mask; 9687077148fSMark Brown int err; 9697077148fSMark Brown 9707077148fSMark Brown err = snd_soc_component_update_bits(component, reg, mask, val1); 9717077148fSMark Brown if (err < 0) 9727077148fSMark Brown return err; 9737077148fSMark Brown 9747077148fSMark Brown return snd_soc_component_update_bits(component, reg, mask, val2); 9757077148fSMark Brown } 9767077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_strobe); 977