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 /** 21034198710SCharles Keepax * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls 21134198710SCharles Keepax * @kcontrol: mixer control 21234198710SCharles Keepax * @uinfo: control element information 21334198710SCharles Keepax * 21434198710SCharles Keepax * Callback to provide information about a single mixer control, or a double 21534198710SCharles Keepax * mixer control that spans 2 registers of the SX TLV type. SX TLV controls 21634198710SCharles Keepax * have a range that represents both positive and negative values either side 21734198710SCharles Keepax * of zero but without a sign bit. 21834198710SCharles Keepax * 21934198710SCharles Keepax * Returns 0 for success. 22034198710SCharles Keepax */ 22134198710SCharles Keepax int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol, 22234198710SCharles Keepax struct snd_ctl_elem_info *uinfo) 22334198710SCharles Keepax { 22434198710SCharles Keepax struct soc_mixer_control *mc = 22534198710SCharles Keepax (struct soc_mixer_control *)kcontrol->private_value; 22634198710SCharles Keepax 22734198710SCharles Keepax snd_soc_info_volsw(kcontrol, uinfo); 22834198710SCharles Keepax /* Max represents the number of levels in an SX control not the 22934198710SCharles Keepax * maximum value, so add the minimum value back on 23034198710SCharles Keepax */ 23134198710SCharles Keepax uinfo->value.integer.max += mc->min; 23234198710SCharles Keepax 23334198710SCharles Keepax return 0; 23434198710SCharles Keepax } 23534198710SCharles Keepax EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx); 23634198710SCharles Keepax 23734198710SCharles Keepax /** 2387077148fSMark Brown * snd_soc_get_volsw - single mixer get callback 2397077148fSMark Brown * @kcontrol: mixer control 2407077148fSMark Brown * @ucontrol: control element information 2417077148fSMark Brown * 2427077148fSMark Brown * Callback to get the value of a single mixer control, or a double mixer 2437077148fSMark Brown * control that spans 2 registers. 2447077148fSMark Brown * 2457077148fSMark Brown * Returns 0 for success. 2467077148fSMark Brown */ 2477077148fSMark Brown int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, 2487077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 2497077148fSMark Brown { 2507077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 2517077148fSMark Brown struct soc_mixer_control *mc = 2527077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 2537077148fSMark Brown unsigned int reg = mc->reg; 2547077148fSMark Brown unsigned int reg2 = mc->rreg; 2557077148fSMark Brown unsigned int shift = mc->shift; 2567077148fSMark Brown unsigned int rshift = mc->rshift; 2577077148fSMark Brown int max = mc->max; 2587077148fSMark Brown int min = mc->min; 2597077148fSMark Brown int sign_bit = mc->sign_bit; 2607077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 2617077148fSMark Brown unsigned int invert = mc->invert; 2627077148fSMark Brown int val; 2637077148fSMark Brown int ret; 2647077148fSMark Brown 2657077148fSMark Brown if (sign_bit) 2667077148fSMark Brown mask = BIT(sign_bit + 1) - 1; 2677077148fSMark Brown 2687077148fSMark Brown ret = snd_soc_read_signed(component, reg, mask, shift, sign_bit, &val); 2697077148fSMark Brown if (ret) 2707077148fSMark Brown return ret; 2717077148fSMark Brown 2727077148fSMark Brown ucontrol->value.integer.value[0] = val - min; 2737077148fSMark Brown if (invert) 2747077148fSMark Brown ucontrol->value.integer.value[0] = 2757077148fSMark Brown max - ucontrol->value.integer.value[0]; 2767077148fSMark Brown 2777077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 2787077148fSMark Brown if (reg == reg2) 2797077148fSMark Brown ret = snd_soc_read_signed(component, reg, mask, rshift, 2807077148fSMark Brown sign_bit, &val); 2817077148fSMark Brown else 2827077148fSMark Brown ret = snd_soc_read_signed(component, reg2, mask, shift, 2837077148fSMark Brown sign_bit, &val); 2847077148fSMark Brown if (ret) 2857077148fSMark Brown return ret; 2867077148fSMark Brown 2877077148fSMark Brown ucontrol->value.integer.value[1] = val - min; 2887077148fSMark Brown if (invert) 2897077148fSMark Brown ucontrol->value.integer.value[1] = 2907077148fSMark Brown max - ucontrol->value.integer.value[1]; 2917077148fSMark Brown } 2927077148fSMark Brown 2937077148fSMark Brown return 0; 2947077148fSMark Brown } 2957077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw); 2967077148fSMark Brown 2977077148fSMark Brown /** 2987077148fSMark Brown * snd_soc_put_volsw - single mixer put callback 2997077148fSMark Brown * @kcontrol: mixer control 3007077148fSMark Brown * @ucontrol: control element information 3017077148fSMark Brown * 3027077148fSMark Brown * Callback to set the value of a single mixer control, or a double mixer 3037077148fSMark Brown * control that spans 2 registers. 3047077148fSMark Brown * 3057077148fSMark Brown * Returns 0 for success. 3067077148fSMark Brown */ 3077077148fSMark Brown int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, 3087077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 3097077148fSMark Brown { 3107077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 3117077148fSMark Brown struct soc_mixer_control *mc = 3127077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 3137077148fSMark Brown unsigned int reg = mc->reg; 3147077148fSMark Brown unsigned int reg2 = mc->rreg; 3157077148fSMark Brown unsigned int shift = mc->shift; 3167077148fSMark Brown unsigned int rshift = mc->rshift; 3177077148fSMark Brown int max = mc->max; 3187077148fSMark Brown int min = mc->min; 3197077148fSMark Brown unsigned int sign_bit = mc->sign_bit; 3207077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 3217077148fSMark Brown unsigned int invert = mc->invert; 3227077148fSMark Brown int err; 3237077148fSMark Brown bool type_2r = false; 3247077148fSMark Brown unsigned int val2 = 0; 3257077148fSMark Brown unsigned int val, val_mask; 3267077148fSMark Brown 3277077148fSMark Brown if (sign_bit) 3287077148fSMark Brown mask = BIT(sign_bit + 1) - 1; 3297077148fSMark Brown 3307077148fSMark Brown val = ((ucontrol->value.integer.value[0] + min) & mask); 3317077148fSMark Brown if (invert) 3327077148fSMark Brown val = max - val; 3337077148fSMark Brown val_mask = mask << shift; 3347077148fSMark Brown val = val << shift; 3357077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 3367077148fSMark Brown val2 = ((ucontrol->value.integer.value[1] + min) & mask); 3377077148fSMark Brown if (invert) 3387077148fSMark Brown val2 = max - val2; 3397077148fSMark Brown if (reg == reg2) { 3407077148fSMark Brown val_mask |= mask << rshift; 3417077148fSMark Brown val |= val2 << rshift; 3427077148fSMark Brown } else { 3437077148fSMark Brown val2 = val2 << shift; 3447077148fSMark Brown type_2r = true; 3457077148fSMark Brown } 3467077148fSMark Brown } 3477077148fSMark Brown err = snd_soc_component_update_bits(component, reg, val_mask, val); 3487077148fSMark Brown if (err < 0) 3497077148fSMark Brown return err; 3507077148fSMark Brown 3517077148fSMark Brown if (type_2r) 3527077148fSMark Brown err = snd_soc_component_update_bits(component, reg2, val_mask, 3537077148fSMark Brown val2); 3547077148fSMark Brown 3557077148fSMark Brown return err; 3567077148fSMark Brown } 3577077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw); 3587077148fSMark Brown 3597077148fSMark Brown /** 3607077148fSMark Brown * snd_soc_get_volsw_sx - single mixer get callback 3617077148fSMark Brown * @kcontrol: mixer control 3627077148fSMark Brown * @ucontrol: control element information 3637077148fSMark Brown * 3647077148fSMark Brown * Callback to get the value of a single mixer control, or a double mixer 3657077148fSMark Brown * control that spans 2 registers. 3667077148fSMark Brown * 3677077148fSMark Brown * Returns 0 for success. 3687077148fSMark Brown */ 3697077148fSMark Brown int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, 3707077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 3717077148fSMark Brown { 3727077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 3737077148fSMark Brown struct soc_mixer_control *mc = 3747077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 3757077148fSMark Brown unsigned int reg = mc->reg; 3767077148fSMark Brown unsigned int reg2 = mc->rreg; 3777077148fSMark Brown unsigned int shift = mc->shift; 3787077148fSMark Brown unsigned int rshift = mc->rshift; 3797077148fSMark Brown int max = mc->max; 3807077148fSMark Brown int min = mc->min; 3817077148fSMark Brown int mask = (1 << (fls(min + max) - 1)) - 1; 3827077148fSMark Brown unsigned int val; 3837077148fSMark Brown int ret; 3847077148fSMark Brown 3857077148fSMark Brown ret = snd_soc_component_read(component, reg, &val); 3867077148fSMark Brown if (ret < 0) 3877077148fSMark Brown return ret; 3887077148fSMark Brown 3897077148fSMark Brown ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; 3907077148fSMark Brown 3917077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 3927077148fSMark Brown ret = snd_soc_component_read(component, reg2, &val); 3937077148fSMark Brown if (ret < 0) 3947077148fSMark Brown return ret; 3957077148fSMark Brown 3967077148fSMark Brown val = ((val >> rshift) - min) & mask; 3977077148fSMark Brown ucontrol->value.integer.value[1] = val; 3987077148fSMark Brown } 3997077148fSMark Brown 4007077148fSMark Brown return 0; 4017077148fSMark Brown } 4027077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_sx); 4037077148fSMark Brown 4047077148fSMark Brown /** 4057077148fSMark Brown * snd_soc_put_volsw_sx - double mixer set callback 4067077148fSMark Brown * @kcontrol: mixer control 4077077148fSMark Brown * @uinfo: control element information 4087077148fSMark Brown * 4097077148fSMark Brown * Callback to set the value of a double mixer control that spans 2 registers. 4107077148fSMark Brown * 4117077148fSMark Brown * Returns 0 for success. 4127077148fSMark Brown */ 4137077148fSMark Brown int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, 4147077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 4157077148fSMark Brown { 4167077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 4177077148fSMark Brown struct soc_mixer_control *mc = 4187077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 4197077148fSMark Brown 4207077148fSMark Brown unsigned int reg = mc->reg; 4217077148fSMark Brown unsigned int reg2 = mc->rreg; 4227077148fSMark Brown unsigned int shift = mc->shift; 4237077148fSMark Brown unsigned int rshift = mc->rshift; 4247077148fSMark Brown int max = mc->max; 4257077148fSMark Brown int min = mc->min; 4267077148fSMark Brown int mask = (1 << (fls(min + max) - 1)) - 1; 4277077148fSMark Brown int err = 0; 4287077148fSMark Brown unsigned int val, val_mask, val2 = 0; 4297077148fSMark Brown 4307077148fSMark Brown val_mask = mask << shift; 4317077148fSMark Brown val = (ucontrol->value.integer.value[0] + min) & mask; 4327077148fSMark Brown val = val << shift; 4337077148fSMark Brown 4347077148fSMark Brown err = snd_soc_component_update_bits(component, reg, val_mask, val); 4357077148fSMark Brown if (err < 0) 4367077148fSMark Brown return err; 4377077148fSMark Brown 4387077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 4397077148fSMark Brown val_mask = mask << rshift; 4407077148fSMark Brown val2 = (ucontrol->value.integer.value[1] + min) & mask; 4417077148fSMark Brown val2 = val2 << rshift; 4427077148fSMark Brown 4437077148fSMark Brown err = snd_soc_component_update_bits(component, reg2, val_mask, 4447077148fSMark Brown val2); 4457077148fSMark Brown } 4467077148fSMark Brown return err; 4477077148fSMark Brown } 4487077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_sx); 4497077148fSMark Brown 4507077148fSMark Brown /** 4517077148fSMark Brown * snd_soc_info_volsw_range - single mixer info callback with range. 4527077148fSMark Brown * @kcontrol: mixer control 4537077148fSMark Brown * @uinfo: control element information 4547077148fSMark Brown * 4557077148fSMark Brown * Callback to provide information, within a range, about a single 4567077148fSMark Brown * mixer control. 4577077148fSMark Brown * 4587077148fSMark Brown * returns 0 for success. 4597077148fSMark Brown */ 4607077148fSMark Brown int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, 4617077148fSMark Brown struct snd_ctl_elem_info *uinfo) 4627077148fSMark Brown { 4637077148fSMark Brown struct soc_mixer_control *mc = 4647077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 4657077148fSMark Brown int platform_max; 4667077148fSMark Brown int min = mc->min; 4677077148fSMark Brown 4687077148fSMark Brown if (!mc->platform_max) 4697077148fSMark Brown mc->platform_max = mc->max; 4707077148fSMark Brown platform_max = mc->platform_max; 4717077148fSMark Brown 4727077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 4737077148fSMark Brown uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; 4747077148fSMark Brown uinfo->value.integer.min = 0; 4757077148fSMark Brown uinfo->value.integer.max = platform_max - min; 4767077148fSMark Brown 4777077148fSMark Brown return 0; 4787077148fSMark Brown } 4797077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); 4807077148fSMark Brown 4817077148fSMark Brown /** 4827077148fSMark Brown * snd_soc_put_volsw_range - single mixer put value callback with range. 4837077148fSMark Brown * @kcontrol: mixer control 4847077148fSMark Brown * @ucontrol: control element information 4857077148fSMark Brown * 4867077148fSMark Brown * Callback to set the value, within a range, for a single mixer control. 4877077148fSMark Brown * 4887077148fSMark Brown * Returns 0 for success. 4897077148fSMark Brown */ 4907077148fSMark Brown int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, 4917077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 4927077148fSMark Brown { 4937077148fSMark Brown struct soc_mixer_control *mc = 4947077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 4957077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 4967077148fSMark Brown unsigned int reg = mc->reg; 4977077148fSMark Brown unsigned int rreg = mc->rreg; 4987077148fSMark Brown unsigned int shift = mc->shift; 4997077148fSMark Brown int min = mc->min; 5007077148fSMark Brown int max = mc->max; 5017077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 5027077148fSMark Brown unsigned int invert = mc->invert; 5037077148fSMark Brown unsigned int val, val_mask; 5047077148fSMark Brown int ret; 5057077148fSMark Brown 5067077148fSMark Brown if (invert) 5077077148fSMark Brown val = (max - ucontrol->value.integer.value[0]) & mask; 5087077148fSMark Brown else 5097077148fSMark Brown val = ((ucontrol->value.integer.value[0] + min) & mask); 5107077148fSMark Brown val_mask = mask << shift; 5117077148fSMark Brown val = val << shift; 5127077148fSMark Brown 5137077148fSMark Brown ret = snd_soc_component_update_bits(component, reg, val_mask, val); 5147077148fSMark Brown if (ret < 0) 5157077148fSMark Brown return ret; 5167077148fSMark Brown 5177077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 5187077148fSMark Brown if (invert) 5197077148fSMark Brown val = (max - ucontrol->value.integer.value[1]) & mask; 5207077148fSMark Brown else 5217077148fSMark Brown val = ((ucontrol->value.integer.value[1] + min) & mask); 5227077148fSMark Brown val_mask = mask << shift; 5237077148fSMark Brown val = val << shift; 5247077148fSMark Brown 5257077148fSMark Brown ret = snd_soc_component_update_bits(component, rreg, val_mask, 5267077148fSMark Brown val); 5277077148fSMark Brown } 5287077148fSMark Brown 5297077148fSMark Brown return ret; 5307077148fSMark Brown } 5317077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); 5327077148fSMark Brown 5337077148fSMark Brown /** 5347077148fSMark Brown * snd_soc_get_volsw_range - single mixer get callback with range 5357077148fSMark Brown * @kcontrol: mixer control 5367077148fSMark Brown * @ucontrol: control element information 5377077148fSMark Brown * 5387077148fSMark Brown * Callback to get the value, within a range, of a single mixer control. 5397077148fSMark Brown * 5407077148fSMark Brown * Returns 0 for success. 5417077148fSMark Brown */ 5427077148fSMark Brown int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, 5437077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 5447077148fSMark Brown { 5457077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 5467077148fSMark Brown struct soc_mixer_control *mc = 5477077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 5487077148fSMark Brown unsigned int reg = mc->reg; 5497077148fSMark Brown unsigned int rreg = mc->rreg; 5507077148fSMark Brown unsigned int shift = mc->shift; 5517077148fSMark Brown int min = mc->min; 5527077148fSMark Brown int max = mc->max; 5537077148fSMark Brown unsigned int mask = (1 << fls(max)) - 1; 5547077148fSMark Brown unsigned int invert = mc->invert; 5557077148fSMark Brown unsigned int val; 5567077148fSMark Brown int ret; 5577077148fSMark Brown 5587077148fSMark Brown ret = snd_soc_component_read(component, reg, &val); 5597077148fSMark Brown if (ret) 5607077148fSMark Brown return ret; 5617077148fSMark Brown 5627077148fSMark Brown ucontrol->value.integer.value[0] = (val >> shift) & mask; 5637077148fSMark Brown if (invert) 5647077148fSMark Brown ucontrol->value.integer.value[0] = 5657077148fSMark Brown max - ucontrol->value.integer.value[0]; 5667077148fSMark Brown else 5677077148fSMark Brown ucontrol->value.integer.value[0] = 5687077148fSMark Brown ucontrol->value.integer.value[0] - min; 5697077148fSMark Brown 5707077148fSMark Brown if (snd_soc_volsw_is_stereo(mc)) { 5717077148fSMark Brown ret = snd_soc_component_read(component, rreg, &val); 5727077148fSMark Brown if (ret) 5737077148fSMark Brown return ret; 5747077148fSMark Brown 5757077148fSMark Brown ucontrol->value.integer.value[1] = (val >> shift) & mask; 5767077148fSMark Brown if (invert) 5777077148fSMark Brown ucontrol->value.integer.value[1] = 5787077148fSMark Brown max - ucontrol->value.integer.value[1]; 5797077148fSMark Brown else 5807077148fSMark Brown ucontrol->value.integer.value[1] = 5817077148fSMark Brown ucontrol->value.integer.value[1] - min; 5827077148fSMark Brown } 5837077148fSMark Brown 5847077148fSMark Brown return 0; 5857077148fSMark Brown } 5867077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); 5877077148fSMark Brown 5887077148fSMark Brown /** 5897077148fSMark Brown * snd_soc_limit_volume - Set new limit to an existing volume control. 5907077148fSMark Brown * 59126d9ca34SLars-Peter Clausen * @card: where to look for the control 5927077148fSMark Brown * @name: Name of the control 5937077148fSMark Brown * @max: new maximum limit 5947077148fSMark Brown * 5957077148fSMark Brown * Return 0 for success, else error. 5967077148fSMark Brown */ 59726d9ca34SLars-Peter Clausen int snd_soc_limit_volume(struct snd_soc_card *card, 5987077148fSMark Brown const char *name, int max) 5997077148fSMark Brown { 60026d9ca34SLars-Peter Clausen struct snd_card *snd_card = card->snd_card; 6017077148fSMark Brown struct snd_kcontrol *kctl; 6027077148fSMark Brown struct soc_mixer_control *mc; 6037077148fSMark Brown int found = 0; 6047077148fSMark Brown int ret = -EINVAL; 6057077148fSMark Brown 6067077148fSMark Brown /* Sanity check for name and max */ 6077077148fSMark Brown if (unlikely(!name || max <= 0)) 6087077148fSMark Brown return -EINVAL; 6097077148fSMark Brown 61026d9ca34SLars-Peter Clausen list_for_each_entry(kctl, &snd_card->controls, list) { 6117077148fSMark Brown if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) { 6127077148fSMark Brown found = 1; 6137077148fSMark Brown break; 6147077148fSMark Brown } 6157077148fSMark Brown } 6167077148fSMark Brown if (found) { 6177077148fSMark Brown mc = (struct soc_mixer_control *)kctl->private_value; 6187077148fSMark Brown if (max <= mc->max) { 6197077148fSMark Brown mc->platform_max = max; 6207077148fSMark Brown ret = 0; 6217077148fSMark Brown } 6227077148fSMark Brown } 6237077148fSMark Brown return ret; 6247077148fSMark Brown } 6257077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_limit_volume); 6267077148fSMark Brown 6277077148fSMark Brown int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, 6287077148fSMark Brown struct snd_ctl_elem_info *uinfo) 6297077148fSMark Brown { 6307077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 6317077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value; 6327077148fSMark Brown 6337077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; 6347077148fSMark Brown uinfo->count = params->num_regs * component->val_bytes; 6357077148fSMark Brown 6367077148fSMark Brown return 0; 6377077148fSMark Brown } 6387077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info); 6397077148fSMark Brown 6407077148fSMark Brown int snd_soc_bytes_get(struct snd_kcontrol *kcontrol, 6417077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 6427077148fSMark Brown { 6437077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 6447077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value; 6457077148fSMark Brown int ret; 6467077148fSMark Brown 6477077148fSMark Brown if (component->regmap) 6487077148fSMark Brown ret = regmap_raw_read(component->regmap, params->base, 6497077148fSMark Brown ucontrol->value.bytes.data, 6507077148fSMark Brown params->num_regs * component->val_bytes); 6517077148fSMark Brown else 6527077148fSMark Brown ret = -EINVAL; 6537077148fSMark Brown 6547077148fSMark Brown /* Hide any masked bytes to ensure consistent data reporting */ 6557077148fSMark Brown if (ret == 0 && params->mask) { 6567077148fSMark Brown switch (component->val_bytes) { 6577077148fSMark Brown case 1: 6587077148fSMark Brown ucontrol->value.bytes.data[0] &= ~params->mask; 6597077148fSMark Brown break; 6607077148fSMark Brown case 2: 6617077148fSMark Brown ((u16 *)(&ucontrol->value.bytes.data))[0] 6627077148fSMark Brown &= cpu_to_be16(~params->mask); 6637077148fSMark Brown break; 6647077148fSMark Brown case 4: 6657077148fSMark Brown ((u32 *)(&ucontrol->value.bytes.data))[0] 6667077148fSMark Brown &= cpu_to_be32(~params->mask); 6677077148fSMark Brown break; 6687077148fSMark Brown default: 6697077148fSMark Brown return -EINVAL; 6707077148fSMark Brown } 6717077148fSMark Brown } 6727077148fSMark Brown 6737077148fSMark Brown return ret; 6747077148fSMark Brown } 6757077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_get); 6767077148fSMark Brown 6777077148fSMark Brown int snd_soc_bytes_put(struct snd_kcontrol *kcontrol, 6787077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 6797077148fSMark Brown { 6807077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 6817077148fSMark Brown struct soc_bytes *params = (void *)kcontrol->private_value; 6827077148fSMark Brown int ret, len; 6837077148fSMark Brown unsigned int val, mask; 6847077148fSMark Brown void *data; 6857077148fSMark Brown 6867077148fSMark Brown if (!component->regmap || !params->num_regs) 6877077148fSMark Brown return -EINVAL; 6887077148fSMark Brown 6897077148fSMark Brown len = params->num_regs * component->val_bytes; 6907077148fSMark Brown 6917077148fSMark Brown data = kmemdup(ucontrol->value.bytes.data, len, GFP_KERNEL | GFP_DMA); 6927077148fSMark Brown if (!data) 6937077148fSMark Brown return -ENOMEM; 6947077148fSMark Brown 6957077148fSMark Brown /* 6967077148fSMark Brown * If we've got a mask then we need to preserve the register 6977077148fSMark Brown * bits. We shouldn't modify the incoming data so take a 6987077148fSMark Brown * copy. 6997077148fSMark Brown */ 7007077148fSMark Brown if (params->mask) { 7017077148fSMark Brown ret = regmap_read(component->regmap, params->base, &val); 7027077148fSMark Brown if (ret != 0) 7037077148fSMark Brown goto out; 7047077148fSMark Brown 7057077148fSMark Brown val &= params->mask; 7067077148fSMark Brown 7077077148fSMark Brown switch (component->val_bytes) { 7087077148fSMark Brown case 1: 7097077148fSMark Brown ((u8 *)data)[0] &= ~params->mask; 7107077148fSMark Brown ((u8 *)data)[0] |= val; 7117077148fSMark Brown break; 7127077148fSMark Brown case 2: 7137077148fSMark Brown mask = ~params->mask; 7147077148fSMark Brown ret = regmap_parse_val(component->regmap, 7157077148fSMark Brown &mask, &mask); 7167077148fSMark Brown if (ret != 0) 7177077148fSMark Brown goto out; 7187077148fSMark Brown 7197077148fSMark Brown ((u16 *)data)[0] &= mask; 7207077148fSMark Brown 7217077148fSMark Brown ret = regmap_parse_val(component->regmap, 7227077148fSMark Brown &val, &val); 7237077148fSMark Brown if (ret != 0) 7247077148fSMark Brown goto out; 7257077148fSMark Brown 7267077148fSMark Brown ((u16 *)data)[0] |= val; 7277077148fSMark Brown break; 7287077148fSMark Brown case 4: 7297077148fSMark Brown mask = ~params->mask; 7307077148fSMark Brown ret = regmap_parse_val(component->regmap, 7317077148fSMark Brown &mask, &mask); 7327077148fSMark Brown if (ret != 0) 7337077148fSMark Brown goto out; 7347077148fSMark Brown 7357077148fSMark Brown ((u32 *)data)[0] &= mask; 7367077148fSMark Brown 7377077148fSMark Brown ret = regmap_parse_val(component->regmap, 7387077148fSMark Brown &val, &val); 7397077148fSMark Brown if (ret != 0) 7407077148fSMark Brown goto out; 7417077148fSMark Brown 7427077148fSMark Brown ((u32 *)data)[0] |= val; 7437077148fSMark Brown break; 7447077148fSMark Brown default: 7457077148fSMark Brown ret = -EINVAL; 7467077148fSMark Brown goto out; 7477077148fSMark Brown } 7487077148fSMark Brown } 7497077148fSMark Brown 7507077148fSMark Brown ret = regmap_raw_write(component->regmap, params->base, 7517077148fSMark Brown data, len); 7527077148fSMark Brown 7537077148fSMark Brown out: 7547077148fSMark Brown kfree(data); 7557077148fSMark Brown 7567077148fSMark Brown return ret; 7577077148fSMark Brown } 7587077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_put); 7597077148fSMark Brown 7607077148fSMark Brown int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol, 7617077148fSMark Brown struct snd_ctl_elem_info *ucontrol) 7627077148fSMark Brown { 7637077148fSMark Brown struct soc_bytes_ext *params = (void *)kcontrol->private_value; 7647077148fSMark Brown 7657077148fSMark Brown ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; 7667077148fSMark Brown ucontrol->count = params->max; 7677077148fSMark Brown 7687077148fSMark Brown return 0; 7697077148fSMark Brown } 7707077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_info_ext); 7717077148fSMark Brown 7727077148fSMark Brown int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, 7737077148fSMark Brown unsigned int size, unsigned int __user *tlv) 7747077148fSMark Brown { 7757077148fSMark Brown struct soc_bytes_ext *params = (void *)kcontrol->private_value; 7767077148fSMark Brown unsigned int count = size < params->max ? size : params->max; 7777077148fSMark Brown int ret = -ENXIO; 7787077148fSMark Brown 7797077148fSMark Brown switch (op_flag) { 7807077148fSMark Brown case SNDRV_CTL_TLV_OP_READ: 7817077148fSMark Brown if (params->get) 782a1e5e7e9SMythri P K ret = params->get(kcontrol, tlv, count); 7837077148fSMark Brown break; 7847077148fSMark Brown case SNDRV_CTL_TLV_OP_WRITE: 7857077148fSMark Brown if (params->put) 786a1e5e7e9SMythri P K ret = params->put(kcontrol, tlv, count); 7877077148fSMark Brown break; 7887077148fSMark Brown } 7897077148fSMark Brown return ret; 7907077148fSMark Brown } 7917077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_bytes_tlv_callback); 7927077148fSMark Brown 7937077148fSMark Brown /** 7947077148fSMark Brown * snd_soc_info_xr_sx - signed multi register info callback 7957077148fSMark Brown * @kcontrol: mreg control 7967077148fSMark Brown * @uinfo: control element information 7977077148fSMark Brown * 7987077148fSMark Brown * Callback to provide information of a control that can 7997077148fSMark Brown * span multiple codec registers which together 8007077148fSMark Brown * forms a single signed value in a MSB/LSB manner. 8017077148fSMark Brown * 8027077148fSMark Brown * Returns 0 for success. 8037077148fSMark Brown */ 8047077148fSMark Brown int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, 8057077148fSMark Brown struct snd_ctl_elem_info *uinfo) 8067077148fSMark Brown { 8077077148fSMark Brown struct soc_mreg_control *mc = 8087077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value; 8097077148fSMark Brown uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 8107077148fSMark Brown uinfo->count = 1; 8117077148fSMark Brown uinfo->value.integer.min = mc->min; 8127077148fSMark Brown uinfo->value.integer.max = mc->max; 8137077148fSMark Brown 8147077148fSMark Brown return 0; 8157077148fSMark Brown } 8167077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_info_xr_sx); 8177077148fSMark Brown 8187077148fSMark Brown /** 8197077148fSMark Brown * snd_soc_get_xr_sx - signed multi register get callback 8207077148fSMark Brown * @kcontrol: mreg control 8217077148fSMark Brown * @ucontrol: control element information 8227077148fSMark Brown * 8237077148fSMark Brown * Callback to get the value of a control that can span 8247077148fSMark Brown * multiple codec registers which together forms a single 8257077148fSMark Brown * signed value in a MSB/LSB manner. The control supports 8267077148fSMark Brown * specifying total no of bits used to allow for bitfields 8277077148fSMark Brown * across the multiple codec registers. 8287077148fSMark Brown * 8297077148fSMark Brown * Returns 0 for success. 8307077148fSMark Brown */ 8317077148fSMark Brown int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, 8327077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 8337077148fSMark Brown { 8347077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 8357077148fSMark Brown struct soc_mreg_control *mc = 8367077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value; 8377077148fSMark Brown unsigned int regbase = mc->regbase; 8387077148fSMark Brown unsigned int regcount = mc->regcount; 8397077148fSMark Brown unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; 8407077148fSMark Brown unsigned int regwmask = (1<<regwshift)-1; 8417077148fSMark Brown unsigned int invert = mc->invert; 8427077148fSMark Brown unsigned long mask = (1UL<<mc->nbits)-1; 8437077148fSMark Brown long min = mc->min; 8447077148fSMark Brown long max = mc->max; 8457077148fSMark Brown long val = 0; 8467077148fSMark Brown unsigned int regval; 8477077148fSMark Brown unsigned int i; 8487077148fSMark Brown int ret; 8497077148fSMark Brown 8507077148fSMark Brown for (i = 0; i < regcount; i++) { 8517077148fSMark Brown ret = snd_soc_component_read(component, regbase+i, ®val); 8527077148fSMark Brown if (ret) 8537077148fSMark Brown return ret; 8547077148fSMark Brown val |= (regval & regwmask) << (regwshift*(regcount-i-1)); 8557077148fSMark Brown } 8567077148fSMark Brown val &= mask; 8577077148fSMark Brown if (min < 0 && val > max) 8587077148fSMark Brown val |= ~mask; 8597077148fSMark Brown if (invert) 8607077148fSMark Brown val = max - val; 8617077148fSMark Brown ucontrol->value.integer.value[0] = val; 8627077148fSMark Brown 8637077148fSMark Brown return 0; 8647077148fSMark Brown } 8657077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx); 8667077148fSMark Brown 8677077148fSMark Brown /** 8687077148fSMark Brown * snd_soc_put_xr_sx - signed multi register get callback 8697077148fSMark Brown * @kcontrol: mreg control 8707077148fSMark Brown * @ucontrol: control element information 8717077148fSMark Brown * 8727077148fSMark Brown * Callback to set the value of a control that can span 8737077148fSMark Brown * multiple codec registers which together forms a single 8747077148fSMark Brown * signed value in a MSB/LSB manner. The control supports 8757077148fSMark Brown * specifying total no of bits used to allow for bitfields 8767077148fSMark Brown * across the multiple codec registers. 8777077148fSMark Brown * 8787077148fSMark Brown * Returns 0 for success. 8797077148fSMark Brown */ 8807077148fSMark Brown int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, 8817077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 8827077148fSMark Brown { 8837077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 8847077148fSMark Brown struct soc_mreg_control *mc = 8857077148fSMark Brown (struct soc_mreg_control *)kcontrol->private_value; 8867077148fSMark Brown unsigned int regbase = mc->regbase; 8877077148fSMark Brown unsigned int regcount = mc->regcount; 8887077148fSMark Brown unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; 8897077148fSMark Brown unsigned int regwmask = (1<<regwshift)-1; 8907077148fSMark Brown unsigned int invert = mc->invert; 8917077148fSMark Brown unsigned long mask = (1UL<<mc->nbits)-1; 8927077148fSMark Brown long max = mc->max; 8937077148fSMark Brown long val = ucontrol->value.integer.value[0]; 8947077148fSMark Brown unsigned int i, regval, regmask; 8957077148fSMark Brown int err; 8967077148fSMark Brown 8977077148fSMark Brown if (invert) 8987077148fSMark Brown val = max - val; 8997077148fSMark Brown val &= mask; 9007077148fSMark Brown for (i = 0; i < regcount; i++) { 9017077148fSMark Brown regval = (val >> (regwshift*(regcount-i-1))) & regwmask; 9027077148fSMark Brown regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; 9037077148fSMark Brown 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 int ret; 9347077148fSMark Brown 9357077148fSMark Brown ret = snd_soc_component_read(component, reg, &val); 9367077148fSMark Brown if (ret) 9377077148fSMark Brown return ret; 9387077148fSMark Brown 9397077148fSMark Brown val &= mask; 9407077148fSMark Brown 9417077148fSMark Brown if (shift != 0 && val != 0) 9427077148fSMark Brown val = val >> shift; 9437077148fSMark Brown ucontrol->value.enumerated.item[0] = val ^ invert; 9447077148fSMark Brown 9457077148fSMark Brown return 0; 9467077148fSMark Brown } 9477077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_get_strobe); 9487077148fSMark Brown 9497077148fSMark Brown /** 9507077148fSMark Brown * snd_soc_put_strobe - strobe put callback 9517077148fSMark Brown * @kcontrol: mixer control 9527077148fSMark Brown * @ucontrol: control element information 9537077148fSMark Brown * 9547077148fSMark Brown * Callback strobe a register bit to high then low (or the inverse) 9557077148fSMark Brown * in one pass of a single mixer enum control. 9567077148fSMark Brown * 9577077148fSMark Brown * Returns 1 for success. 9587077148fSMark Brown */ 9597077148fSMark Brown int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, 9607077148fSMark Brown struct snd_ctl_elem_value *ucontrol) 9617077148fSMark Brown { 9627077148fSMark Brown struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); 9637077148fSMark Brown struct soc_mixer_control *mc = 9647077148fSMark Brown (struct soc_mixer_control *)kcontrol->private_value; 9657077148fSMark Brown unsigned int reg = mc->reg; 9667077148fSMark Brown unsigned int shift = mc->shift; 9677077148fSMark Brown unsigned int mask = 1 << shift; 9687077148fSMark Brown unsigned int invert = mc->invert != 0; 9697077148fSMark Brown unsigned int strobe = ucontrol->value.enumerated.item[0] != 0; 9707077148fSMark Brown unsigned int val1 = (strobe ^ invert) ? mask : 0; 9717077148fSMark Brown unsigned int val2 = (strobe ^ invert) ? 0 : mask; 9727077148fSMark Brown int err; 9737077148fSMark Brown 9747077148fSMark Brown err = snd_soc_component_update_bits(component, reg, mask, val1); 9757077148fSMark Brown if (err < 0) 9767077148fSMark Brown return err; 9777077148fSMark Brown 9787077148fSMark Brown return snd_soc_component_update_bits(component, reg, mask, val2); 9797077148fSMark Brown } 9807077148fSMark Brown EXPORT_SYMBOL_GPL(snd_soc_put_strobe); 981