2018-07-02 09:22:30 +03:00
// SPDX-License-Identifier: GPL-2.0+
//
// soc-ops.c -- Generic ASoC operations
//
// Copyright 2005 Wolfson Microelectronics PLC.
// Copyright 2005 Openedhand Ltd.
// Copyright (C) 2010 Slimlogic Ltd.
// Copyright (C) 2010 Texas Instruments Inc.
//
// Author: Liam Girdwood <lrg@slimlogic.co.uk>
// with code, comments and ideas from :-
// Richard Purdie <richard@openedhand.com>
2014-10-29 01:15:31 +03:00
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/init.h>
# include <linux/pm.h>
# include <linux/bitops.h>
# include <linux/ctype.h>
# include <linux/slab.h>
# include <sound/core.h>
# include <sound/jack.h>
# include <sound/pcm.h>
# include <sound/pcm_params.h>
# include <sound/soc.h>
# include <sound/soc-dpcm.h>
# include <sound/initval.h>
/**
* snd_soc_info_enum_double - enumerated double mixer info callback
* @ kcontrol : mixer control
* @ uinfo : control element information
*
* Callback to provide information about a double enumerated
* mixer control .
*
* Returns 0 for success .
*/
int snd_soc_info_enum_double ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo )
{
struct soc_enum * e = ( struct soc_enum * ) kcontrol - > private_value ;
return snd_ctl_enum_info ( uinfo , e - > shift_l = = e - > shift_r ? 1 : 2 ,
e - > items , e - > texts ) ;
}
EXPORT_SYMBOL_GPL ( snd_soc_info_enum_double ) ;
/**
* snd_soc_get_enum_double - enumerated double mixer get callback
* @ kcontrol : mixer control
* @ ucontrol : control element information
*
* Callback to get the value of a double enumerated mixer .
*
* Returns 0 for success .
*/
int snd_soc_get_enum_double ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_enum * e = ( struct soc_enum * ) kcontrol - > private_value ;
unsigned int val , item ;
unsigned int reg_val ;
ASoC: soc-component: merge snd_soc_component_read() and snd_soc_component_read32()
We had read/write function for Codec, Platform, etc,
but these has been merged into snd_soc_component_read/write().
Internally, it is using regmap or driver function.
In read case, each styles are like below
regmap
ret = regmap_read(..., reg, &val);
driver function
val = xxx->read(..., reg);
Because of this kind of different style, to keep same read style,
when we merged each read function into snd_soc_component_read(),
we created snd_soc_component_read32(), like below.
commit 738b49efe6c6 ("ASoC: add snd_soc_component_read32")
(1) val = snd_soc_component_read32(component, reg);
(2) ret = snd_soc_component_read(component, reg, &val);
Many drivers are using snd_soc_component_read32(), and
some drivers are using snd_soc_component_read() today.
In generally, we don't check read function successes,
because, we will have many other issues at initial timing
if read function didn't work.
Now we can use soc_component_err() when error case.
This means, it is easy to notice if error occurred.
This patch aggressively merge snd_soc_component_read() and _read32(),
and makes snd_soc_component_read/write() as generally style.
This patch do
1) merge snd_soc_component_read() and snd_soc_component_read32()
2) it uses soc_component_err() when error case (easy to notice)
3) keeps read32 for now by #define
4) update snd_soc_component_read() for all drivers
Because _read() user drivers are not too many, this patch changes
all user drivers.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/87sgev4mfl.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-16 08:19:41 +03:00
reg_val = snd_soc_component_read ( component , e - > reg ) ;
2014-10-29 01:15:31 +03:00
val = ( reg_val > > e - > shift_l ) & e - > mask ;
item = snd_soc_enum_val_to_item ( e , val ) ;
ucontrol - > value . enumerated . item [ 0 ] = item ;
if ( e - > shift_l ! = e - > shift_r ) {
2016-08-29 18:06:58 +03:00
val = ( reg_val > > e - > shift_r ) & e - > mask ;
2014-10-29 01:15:31 +03:00
item = snd_soc_enum_val_to_item ( e , val ) ;
ucontrol - > value . enumerated . item [ 1 ] = item ;
}
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_get_enum_double ) ;
/**
* snd_soc_put_enum_double - enumerated double mixer put callback
* @ kcontrol : mixer control
* @ ucontrol : control element information
*
* Callback to set the value of a double enumerated mixer .
*
* Returns 0 for success .
*/
int snd_soc_put_enum_double ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_enum * e = ( struct soc_enum * ) kcontrol - > private_value ;
unsigned int * item = ucontrol - > value . enumerated . item ;
unsigned int val ;
unsigned int mask ;
if ( item [ 0 ] > = e - > items )
return - EINVAL ;
val = snd_soc_enum_item_to_val ( e , item [ 0 ] ) < < e - > shift_l ;
mask = e - > mask < < e - > shift_l ;
if ( e - > shift_l ! = e - > shift_r ) {
if ( item [ 1 ] > = e - > items )
return - EINVAL ;
val | = snd_soc_enum_item_to_val ( e , item [ 1 ] ) < < e - > shift_r ;
mask | = e - > mask < < e - > shift_r ;
}
return snd_soc_component_update_bits ( component , e - > reg , mask , val ) ;
}
EXPORT_SYMBOL_GPL ( snd_soc_put_enum_double ) ;
/**
2017-01-12 14:38:15 +03:00
* snd_soc_read_signed - Read a codec register and interpret as signed value
2014-10-29 01:15:31 +03:00
* @ component : component
* @ reg : Register to read
* @ mask : Mask to use after shifting the register value
* @ shift : Right shift of register value
* @ sign_bit : Bit that describes if a number is negative or not .
* @ signed_val : Pointer to where the read value should be stored
*
* This functions reads a codec register . The register value is shifted right
* by ' shift ' bits and masked with the given ' mask ' . Afterwards it translates
* the given registervalue into a signed integer if sign_bit is non - zero .
*
* Returns 0 on sucess , otherwise an error value
*/
static int snd_soc_read_signed ( struct snd_soc_component * component ,
unsigned int reg , unsigned int mask , unsigned int shift ,
unsigned int sign_bit , int * signed_val )
{
int ret ;
unsigned int val ;
ASoC: soc-component: merge snd_soc_component_read() and snd_soc_component_read32()
We had read/write function for Codec, Platform, etc,
but these has been merged into snd_soc_component_read/write().
Internally, it is using regmap or driver function.
In read case, each styles are like below
regmap
ret = regmap_read(..., reg, &val);
driver function
val = xxx->read(..., reg);
Because of this kind of different style, to keep same read style,
when we merged each read function into snd_soc_component_read(),
we created snd_soc_component_read32(), like below.
commit 738b49efe6c6 ("ASoC: add snd_soc_component_read32")
(1) val = snd_soc_component_read32(component, reg);
(2) ret = snd_soc_component_read(component, reg, &val);
Many drivers are using snd_soc_component_read32(), and
some drivers are using snd_soc_component_read() today.
In generally, we don't check read function successes,
because, we will have many other issues at initial timing
if read function didn't work.
Now we can use soc_component_err() when error case.
This means, it is easy to notice if error occurred.
This patch aggressively merge snd_soc_component_read() and _read32(),
and makes snd_soc_component_read/write() as generally style.
This patch do
1) merge snd_soc_component_read() and snd_soc_component_read32()
2) it uses soc_component_err() when error case (easy to notice)
3) keeps read32 for now by #define
4) update snd_soc_component_read() for all drivers
Because _read() user drivers are not too many, this patch changes
all user drivers.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/87sgev4mfl.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-16 08:19:41 +03:00
val = snd_soc_component_read ( component , reg ) ;
2014-10-29 01:15:31 +03:00
val = ( val > > shift ) & mask ;
if ( ! sign_bit ) {
* signed_val = val ;
return 0 ;
}
/* non-negative number */
if ( ! ( val & BIT ( sign_bit ) ) ) {
* signed_val = val ;
return 0 ;
}
ret = val ;
/*
* The register most probably does not contain a full - sized int .
* Instead we have an arbitrary number of bits in a signed
* representation which has to be translated into a full - sized int .
* This is done by filling up all bits above the sign - bit .
*/
ret | = ~ ( ( int ) ( BIT ( sign_bit ) - 1 ) ) ;
* signed_val = ret ;
return 0 ;
}
/**
* snd_soc_info_volsw - single mixer info callback
* @ kcontrol : mixer control
* @ uinfo : control element information
*
* Callback to provide information about a single mixer control , or a double
* mixer control that spans 2 registers .
*
* Returns 0 for success .
*/
int snd_soc_info_volsw ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo )
{
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
2022-06-04 13:54:07 +03:00
const char * vol_string = NULL ;
2022-06-03 14:25:08 +03:00
int max ;
2014-10-29 01:15:31 +03:00
2022-06-03 14:25:08 +03:00
max = uinfo - > value . integer . max = mc - > max - mc - > min ;
if ( mc - > platform_max & & mc - > platform_max < max )
max = mc - > platform_max ;
2014-10-29 01:15:31 +03:00
2022-06-04 13:54:07 +03:00
if ( max = = 1 ) {
2022-06-17 18:36:06 +03:00
/* Even two value controls ending in Volume should always be integer */
2022-06-04 13:54:07 +03:00
vol_string = strstr ( kcontrol - > id . name , " Volume " ) ;
2022-06-17 18:36:06 +03:00
if ( vol_string & & ! strcmp ( vol_string , " Volume " ) )
uinfo - > type = SNDRV_CTL_ELEM_TYPE_INTEGER ;
else
uinfo - > type = SNDRV_CTL_ELEM_TYPE_BOOLEAN ;
} else {
2014-10-29 01:15:31 +03:00
uinfo - > type = SNDRV_CTL_ELEM_TYPE_INTEGER ;
2022-06-17 18:36:06 +03:00
}
2014-10-29 01:15:31 +03:00
uinfo - > count = snd_soc_volsw_is_stereo ( mc ) ? 2 : 1 ;
uinfo - > value . integer . min = 0 ;
2022-06-03 14:25:08 +03:00
uinfo - > value . integer . max = max ;
2014-10-29 01:15:31 +03:00
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_info_volsw ) ;
2015-10-14 15:31:24 +03:00
/**
* snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
* @ kcontrol : mixer control
* @ uinfo : control element information
*
* Callback to provide information about a single mixer control , or a double
* mixer control that spans 2 registers of the SX TLV type . SX TLV controls
* have a range that represents both positive and negative values either side
2022-06-02 12:29:20 +03:00
* of zero but without a sign bit . min is the minimum register value , max is
* the number of steps .
2015-10-14 15:31:24 +03:00
*
* Returns 0 for success .
*/
int snd_soc_info_volsw_sx ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo )
{
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
2022-06-02 12:29:20 +03:00
int max ;
2015-10-14 15:31:24 +03:00
2022-06-02 12:29:20 +03:00
if ( mc - > platform_max )
max = mc - > platform_max ;
else
max = mc - > max ;
if ( max = = 1 & & ! strstr ( kcontrol - > id . name , " Volume " ) )
uinfo - > type = SNDRV_CTL_ELEM_TYPE_BOOLEAN ;
else
uinfo - > type = SNDRV_CTL_ELEM_TYPE_INTEGER ;
uinfo - > count = snd_soc_volsw_is_stereo ( mc ) ? 2 : 1 ;
uinfo - > value . integer . min = 0 ;
uinfo - > value . integer . max = max ;
2015-10-14 15:31:24 +03:00
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_info_volsw_sx ) ;
2014-10-29 01:15:31 +03:00
/**
* snd_soc_get_volsw - single mixer get callback
* @ kcontrol : mixer control
* @ ucontrol : control element information
*
* Callback to get the value of a single mixer control , or a double mixer
* control that spans 2 registers .
*
* Returns 0 for success .
*/
int snd_soc_get_volsw ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
unsigned int reg = mc - > reg ;
unsigned int reg2 = mc - > rreg ;
unsigned int shift = mc - > shift ;
unsigned int rshift = mc - > rshift ;
int max = mc - > max ;
int min = mc - > min ;
int sign_bit = mc - > sign_bit ;
unsigned int mask = ( 1 < < fls ( max ) ) - 1 ;
unsigned int invert = mc - > invert ;
int val ;
int ret ;
if ( sign_bit )
mask = BIT ( sign_bit + 1 ) - 1 ;
ret = snd_soc_read_signed ( component , reg , mask , shift , sign_bit , & val ) ;
if ( ret )
return ret ;
ucontrol - > value . integer . value [ 0 ] = val - min ;
if ( invert )
ucontrol - > value . integer . value [ 0 ] =
max - ucontrol - > value . integer . value [ 0 ] ;
if ( snd_soc_volsw_is_stereo ( mc ) ) {
if ( reg = = reg2 )
ret = snd_soc_read_signed ( component , reg , mask , rshift ,
sign_bit , & val ) ;
else
ret = snd_soc_read_signed ( component , reg2 , mask , shift ,
sign_bit , & val ) ;
if ( ret )
return ret ;
ucontrol - > value . integer . value [ 1 ] = val - min ;
if ( invert )
ucontrol - > value . integer . value [ 1 ] =
max - ucontrol - > value . integer . value [ 1 ] ;
}
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_get_volsw ) ;
/**
* snd_soc_put_volsw - single mixer put callback
* @ kcontrol : mixer control
* @ ucontrol : control element information
*
* Callback to set the value of a single mixer control , or a double mixer
* control that spans 2 registers .
*
* Returns 0 for success .
*/
int snd_soc_put_volsw ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
unsigned int reg = mc - > reg ;
unsigned int reg2 = mc - > rreg ;
unsigned int shift = mc - > shift ;
unsigned int rshift = mc - > rshift ;
int max = mc - > max ;
int min = mc - > min ;
unsigned int sign_bit = mc - > sign_bit ;
unsigned int mask = ( 1 < < fls ( max ) ) - 1 ;
unsigned int invert = mc - > invert ;
2022-02-01 18:56:26 +03:00
int err , ret ;
2014-10-29 01:15:31 +03:00
bool type_2r = false ;
unsigned int val2 = 0 ;
unsigned int val , val_mask ;
if ( sign_bit )
mask = BIT ( sign_bit + 1 ) - 1 ;
2022-01-28 22:24:43 +03:00
if ( ucontrol - > value . integer . value [ 0 ] < 0 )
return - EINVAL ;
2022-01-24 18:32:51 +03:00
val = ucontrol - > value . integer . value [ 0 ] ;
2022-02-15 16:06:45 +03:00
if ( mc - > platform_max & & ( ( int ) val + min ) > mc - > platform_max )
2022-01-24 18:32:51 +03:00
return - EINVAL ;
if ( val > max - min )
return - EINVAL ;
val = ( val + min ) & mask ;
2014-10-29 01:15:31 +03:00
if ( invert )
val = max - val ;
val_mask = mask < < shift ;
val = val < < shift ;
if ( snd_soc_volsw_is_stereo ( mc ) ) {
2022-01-28 22:24:43 +03:00
if ( ucontrol - > value . integer . value [ 1 ] < 0 )
return - EINVAL ;
2022-01-24 18:32:51 +03:00
val2 = ucontrol - > value . integer . value [ 1 ] ;
2022-02-15 16:06:45 +03:00
if ( mc - > platform_max & & ( ( int ) val2 + min ) > mc - > platform_max )
2022-01-24 18:32:51 +03:00
return - EINVAL ;
if ( val2 > max - min )
return - EINVAL ;
val2 = ( val2 + min ) & mask ;
2014-10-29 01:15:31 +03:00
if ( invert )
val2 = max - val2 ;
if ( reg = = reg2 ) {
val_mask | = mask < < rshift ;
val | = val2 < < rshift ;
} else {
val2 = val2 < < shift ;
type_2r = true ;
}
}
err = snd_soc_component_update_bits ( component , reg , val_mask , val ) ;
if ( err < 0 )
return err ;
2022-02-01 18:56:26 +03:00
ret = err ;
2014-10-29 01:15:31 +03:00
2022-02-01 18:56:26 +03:00
if ( type_2r ) {
2014-10-29 01:15:31 +03:00
err = snd_soc_component_update_bits ( component , reg2 , val_mask ,
2022-02-01 18:56:26 +03:00
val2 ) ;
/* Don't discard any error code or drop change flag */
if ( ret = = 0 | | err < 0 ) {
ret = err ;
}
}
2014-10-29 01:15:31 +03:00
2022-02-01 18:56:26 +03:00
return ret ;
2014-10-29 01:15:31 +03:00
}
EXPORT_SYMBOL_GPL ( snd_soc_put_volsw ) ;
/**
* snd_soc_get_volsw_sx - single mixer get callback
* @ kcontrol : mixer control
* @ ucontrol : control element information
*
* Callback to get the value of a single mixer control , or a double mixer
* control that spans 2 registers .
*
* Returns 0 for success .
*/
int snd_soc_get_volsw_sx ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
unsigned int reg = mc - > reg ;
unsigned int reg2 = mc - > rreg ;
unsigned int shift = mc - > shift ;
unsigned int rshift = mc - > rshift ;
int max = mc - > max ;
int min = mc - > min ;
2018-09-11 12:29:21 +03:00
unsigned int mask = ( 1U < < ( fls ( min + max ) - 1 ) ) - 1 ;
2014-10-29 01:15:31 +03:00
unsigned int val ;
ASoC: soc-component: merge snd_soc_component_read() and snd_soc_component_read32()
We had read/write function for Codec, Platform, etc,
but these has been merged into snd_soc_component_read/write().
Internally, it is using regmap or driver function.
In read case, each styles are like below
regmap
ret = regmap_read(..., reg, &val);
driver function
val = xxx->read(..., reg);
Because of this kind of different style, to keep same read style,
when we merged each read function into snd_soc_component_read(),
we created snd_soc_component_read32(), like below.
commit 738b49efe6c6 ("ASoC: add snd_soc_component_read32")
(1) val = snd_soc_component_read32(component, reg);
(2) ret = snd_soc_component_read(component, reg, &val);
Many drivers are using snd_soc_component_read32(), and
some drivers are using snd_soc_component_read() today.
In generally, we don't check read function successes,
because, we will have many other issues at initial timing
if read function didn't work.
Now we can use soc_component_err() when error case.
This means, it is easy to notice if error occurred.
This patch aggressively merge snd_soc_component_read() and _read32(),
and makes snd_soc_component_read/write() as generally style.
This patch do
1) merge snd_soc_component_read() and snd_soc_component_read32()
2) it uses soc_component_err() when error case (easy to notice)
3) keeps read32 for now by #define
4) update snd_soc_component_read() for all drivers
Because _read() user drivers are not too many, this patch changes
all user drivers.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/87sgev4mfl.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-16 08:19:41 +03:00
val = snd_soc_component_read ( component , reg ) ;
2014-10-29 01:15:31 +03:00
ucontrol - > value . integer . value [ 0 ] = ( ( val > > shift ) - min ) & mask ;
if ( snd_soc_volsw_is_stereo ( mc ) ) {
ASoC: soc-component: merge snd_soc_component_read() and snd_soc_component_read32()
We had read/write function for Codec, Platform, etc,
but these has been merged into snd_soc_component_read/write().
Internally, it is using regmap or driver function.
In read case, each styles are like below
regmap
ret = regmap_read(..., reg, &val);
driver function
val = xxx->read(..., reg);
Because of this kind of different style, to keep same read style,
when we merged each read function into snd_soc_component_read(),
we created snd_soc_component_read32(), like below.
commit 738b49efe6c6 ("ASoC: add snd_soc_component_read32")
(1) val = snd_soc_component_read32(component, reg);
(2) ret = snd_soc_component_read(component, reg, &val);
Many drivers are using snd_soc_component_read32(), and
some drivers are using snd_soc_component_read() today.
In generally, we don't check read function successes,
because, we will have many other issues at initial timing
if read function didn't work.
Now we can use soc_component_err() when error case.
This means, it is easy to notice if error occurred.
This patch aggressively merge snd_soc_component_read() and _read32(),
and makes snd_soc_component_read/write() as generally style.
This patch do
1) merge snd_soc_component_read() and snd_soc_component_read32()
2) it uses soc_component_err() when error case (easy to notice)
3) keeps read32 for now by #define
4) update snd_soc_component_read() for all drivers
Because _read() user drivers are not too many, this patch changes
all user drivers.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/87sgev4mfl.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-16 08:19:41 +03:00
val = snd_soc_component_read ( component , reg2 ) ;
2014-10-29 01:15:31 +03:00
val = ( ( val > > rshift ) - min ) & mask ;
ucontrol - > value . integer . value [ 1 ] = val ;
}
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_get_volsw_sx ) ;
/**
* snd_soc_put_volsw_sx - double mixer set callback
* @ kcontrol : mixer control
2015-11-24 04:37:54 +03:00
* @ ucontrol : control element information
2014-10-29 01:15:31 +03:00
*
* Callback to set the value of a double mixer control that spans 2 registers .
*
* Returns 0 for success .
*/
int snd_soc_put_volsw_sx ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
unsigned int reg = mc - > reg ;
unsigned int reg2 = mc - > rreg ;
unsigned int shift = mc - > shift ;
unsigned int rshift = mc - > rshift ;
int max = mc - > max ;
int min = mc - > min ;
2018-09-11 12:29:21 +03:00
unsigned int mask = ( 1U < < ( fls ( min + max ) - 1 ) ) - 1 ;
2014-10-29 01:15:31 +03:00
int err = 0 ;
2022-02-01 18:56:27 +03:00
int ret ;
2021-08-03 08:00:37 +03:00
unsigned int val , val_mask ;
2014-10-29 01:15:31 +03:00
2022-01-28 22:24:43 +03:00
if ( ucontrol - > value . integer . value [ 0 ] < 0 )
return - EINVAL ;
2022-01-24 18:32:52 +03:00
val = ucontrol - > value . integer . value [ 0 ] ;
if ( mc - > platform_max & & val > mc - > platform_max )
return - EINVAL ;
2022-05-11 16:41:36 +03:00
if ( val > max )
2022-01-24 18:32:52 +03:00
return - EINVAL ;
2014-10-29 01:15:31 +03:00
val_mask = mask < < shift ;
2022-01-24 18:32:52 +03:00
val = ( val + min ) & mask ;
2014-10-29 01:15:31 +03:00
val = val < < shift ;
err = snd_soc_component_update_bits ( component , reg , val_mask , val ) ;
if ( err < 0 )
return err ;
2022-02-01 18:56:27 +03:00
ret = err ;
2014-10-29 01:15:31 +03:00
if ( snd_soc_volsw_is_stereo ( mc ) ) {
2022-11-25 19:23:47 +03:00
unsigned int val2 = ucontrol - > value . integer . value [ 1 ] ;
2022-05-11 16:41:37 +03:00
if ( mc - > platform_max & & val2 > mc - > platform_max )
return - EINVAL ;
if ( val2 > max )
return - EINVAL ;
2022-11-25 19:23:47 +03:00
val_mask = mask < < rshift ;
val2 = ( val2 + min ) & mask ;
2014-10-29 01:15:31 +03:00
val2 = val2 < < rshift ;
err = snd_soc_component_update_bits ( component , reg2 , val_mask ,
val2 ) ;
2022-02-01 18:56:27 +03:00
/* Don't discard any error code or drop change flag */
if ( ret = = 0 | | err < 0 ) {
ret = err ;
}
2014-10-29 01:15:31 +03:00
}
2022-04-21 19:23:28 +03:00
return ret ;
2014-10-29 01:15:31 +03:00
}
EXPORT_SYMBOL_GPL ( snd_soc_put_volsw_sx ) ;
/**
* snd_soc_info_volsw_range - single mixer info callback with range .
* @ kcontrol : mixer control
* @ uinfo : control element information
*
* Callback to provide information , within a range , about a single
* mixer control .
*
* returns 0 for success .
*/
int snd_soc_info_volsw_range ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo )
{
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
int platform_max ;
int min = mc - > min ;
if ( ! mc - > platform_max )
mc - > platform_max = mc - > max ;
platform_max = mc - > platform_max ;
uinfo - > type = SNDRV_CTL_ELEM_TYPE_INTEGER ;
uinfo - > count = snd_soc_volsw_is_stereo ( mc ) ? 2 : 1 ;
uinfo - > value . integer . min = 0 ;
uinfo - > value . integer . max = platform_max - min ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_info_volsw_range ) ;
/**
* snd_soc_put_volsw_range - single mixer put value callback with range .
* @ kcontrol : mixer control
* @ ucontrol : control element information
*
* Callback to set the value , within a range , for a single mixer control .
*
* Returns 0 for success .
*/
int snd_soc_put_volsw_range ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
unsigned int reg = mc - > reg ;
unsigned int rreg = mc - > rreg ;
unsigned int shift = mc - > shift ;
int min = mc - > min ;
int max = mc - > max ;
unsigned int mask = ( 1 < < fls ( max ) ) - 1 ;
unsigned int invert = mc - > invert ;
unsigned int val , val_mask ;
2022-04-23 16:12:39 +03:00
int err , ret , tmp ;
tmp = ucontrol - > value . integer . value [ 0 ] ;
if ( tmp < 0 )
return - EINVAL ;
if ( mc - > platform_max & & tmp > mc - > platform_max )
return - EINVAL ;
2022-06-04 13:52:46 +03:00
if ( tmp > mc - > max - mc - > min )
2022-04-23 16:12:39 +03:00
return - EINVAL ;
2014-10-29 01:15:31 +03:00
if ( invert )
val = ( max - ucontrol - > value . integer . value [ 0 ] ) & mask ;
else
val = ( ( ucontrol - > value . integer . value [ 0 ] + min ) & mask ) ;
val_mask = mask < < shift ;
val = val < < shift ;
2022-02-01 18:56:28 +03:00
err = snd_soc_component_update_bits ( component , reg , val_mask , val ) ;
if ( err < 0 )
return err ;
ret = err ;
2014-10-29 01:15:31 +03:00
if ( snd_soc_volsw_is_stereo ( mc ) ) {
2022-04-23 16:12:39 +03:00
tmp = ucontrol - > value . integer . value [ 1 ] ;
if ( tmp < 0 )
return - EINVAL ;
if ( mc - > platform_max & & tmp > mc - > platform_max )
return - EINVAL ;
2022-06-04 13:52:46 +03:00
if ( tmp > mc - > max - mc - > min )
2022-04-23 16:12:39 +03:00
return - EINVAL ;
2014-10-29 01:15:31 +03:00
if ( invert )
val = ( max - ucontrol - > value . integer . value [ 1 ] ) & mask ;
else
val = ( ( ucontrol - > value . integer . value [ 1 ] + min ) & mask ) ;
val_mask = mask < < shift ;
val = val < < shift ;
2022-02-01 18:56:28 +03:00
err = snd_soc_component_update_bits ( component , rreg , val_mask ,
2014-10-29 01:15:31 +03:00
val ) ;
2022-02-01 18:56:28 +03:00
/* Don't discard any error code or drop change flag */
if ( ret = = 0 | | err < 0 ) {
ret = err ;
}
2014-10-29 01:15:31 +03:00
}
return ret ;
}
EXPORT_SYMBOL_GPL ( snd_soc_put_volsw_range ) ;
/**
* snd_soc_get_volsw_range - single mixer get callback with range
* @ kcontrol : mixer control
* @ ucontrol : control element information
*
* Callback to get the value , within a range , of a single mixer control .
*
* Returns 0 for success .
*/
int snd_soc_get_volsw_range ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
unsigned int reg = mc - > reg ;
unsigned int rreg = mc - > rreg ;
unsigned int shift = mc - > shift ;
int min = mc - > min ;
int max = mc - > max ;
unsigned int mask = ( 1 < < fls ( max ) ) - 1 ;
unsigned int invert = mc - > invert ;
unsigned int val ;
ASoC: soc-component: merge snd_soc_component_read() and snd_soc_component_read32()
We had read/write function for Codec, Platform, etc,
but these has been merged into snd_soc_component_read/write().
Internally, it is using regmap or driver function.
In read case, each styles are like below
regmap
ret = regmap_read(..., reg, &val);
driver function
val = xxx->read(..., reg);
Because of this kind of different style, to keep same read style,
when we merged each read function into snd_soc_component_read(),
we created snd_soc_component_read32(), like below.
commit 738b49efe6c6 ("ASoC: add snd_soc_component_read32")
(1) val = snd_soc_component_read32(component, reg);
(2) ret = snd_soc_component_read(component, reg, &val);
Many drivers are using snd_soc_component_read32(), and
some drivers are using snd_soc_component_read() today.
In generally, we don't check read function successes,
because, we will have many other issues at initial timing
if read function didn't work.
Now we can use soc_component_err() when error case.
This means, it is easy to notice if error occurred.
This patch aggressively merge snd_soc_component_read() and _read32(),
and makes snd_soc_component_read/write() as generally style.
This patch do
1) merge snd_soc_component_read() and snd_soc_component_read32()
2) it uses soc_component_err() when error case (easy to notice)
3) keeps read32 for now by #define
4) update snd_soc_component_read() for all drivers
Because _read() user drivers are not too many, this patch changes
all user drivers.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/87sgev4mfl.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-16 08:19:41 +03:00
val = snd_soc_component_read ( component , reg ) ;
2014-10-29 01:15:31 +03:00
ucontrol - > value . integer . value [ 0 ] = ( val > > shift ) & mask ;
if ( invert )
ucontrol - > value . integer . value [ 0 ] =
max - ucontrol - > value . integer . value [ 0 ] ;
else
ucontrol - > value . integer . value [ 0 ] =
ucontrol - > value . integer . value [ 0 ] - min ;
if ( snd_soc_volsw_is_stereo ( mc ) ) {
ASoC: soc-component: merge snd_soc_component_read() and snd_soc_component_read32()
We had read/write function for Codec, Platform, etc,
but these has been merged into snd_soc_component_read/write().
Internally, it is using regmap or driver function.
In read case, each styles are like below
regmap
ret = regmap_read(..., reg, &val);
driver function
val = xxx->read(..., reg);
Because of this kind of different style, to keep same read style,
when we merged each read function into snd_soc_component_read(),
we created snd_soc_component_read32(), like below.
commit 738b49efe6c6 ("ASoC: add snd_soc_component_read32")
(1) val = snd_soc_component_read32(component, reg);
(2) ret = snd_soc_component_read(component, reg, &val);
Many drivers are using snd_soc_component_read32(), and
some drivers are using snd_soc_component_read() today.
In generally, we don't check read function successes,
because, we will have many other issues at initial timing
if read function didn't work.
Now we can use soc_component_err() when error case.
This means, it is easy to notice if error occurred.
This patch aggressively merge snd_soc_component_read() and _read32(),
and makes snd_soc_component_read/write() as generally style.
This patch do
1) merge snd_soc_component_read() and snd_soc_component_read32()
2) it uses soc_component_err() when error case (easy to notice)
3) keeps read32 for now by #define
4) update snd_soc_component_read() for all drivers
Because _read() user drivers are not too many, this patch changes
all user drivers.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/87sgev4mfl.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-16 08:19:41 +03:00
val = snd_soc_component_read ( component , rreg ) ;
2014-10-29 01:15:31 +03:00
ucontrol - > value . integer . value [ 1 ] = ( val > > shift ) & mask ;
if ( invert )
ucontrol - > value . integer . value [ 1 ] =
max - ucontrol - > value . integer . value [ 1 ] ;
else
ucontrol - > value . integer . value [ 1 ] =
ucontrol - > value . integer . value [ 1 ] - min ;
}
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_get_volsw_range ) ;
/**
* snd_soc_limit_volume - Set new limit to an existing volume control .
*
2015-10-18 18:04:33 +03:00
* @ card : where to look for the control
2014-10-29 01:15:31 +03:00
* @ name : Name of the control
* @ max : new maximum limit
*
* Return 0 for success , else error .
*/
2015-10-18 18:04:33 +03:00
int snd_soc_limit_volume ( struct snd_soc_card * card ,
2014-10-29 01:15:31 +03:00
const char * name , int max )
{
struct snd_kcontrol * kctl ;
int ret = - EINVAL ;
/* Sanity check for name and max */
if ( unlikely ( ! name | | max < = 0 ) )
return - EINVAL ;
2019-10-02 08:23:14 +03:00
kctl = snd_soc_card_get_kcontrol ( card , name ) ;
if ( kctl ) {
2021-08-03 08:00:49 +03:00
struct soc_mixer_control * mc = ( struct soc_mixer_control * ) kctl - > private_value ;
2014-10-29 01:15:31 +03:00
if ( max < = mc - > max ) {
mc - > platform_max = max ;
ret = 0 ;
}
}
return ret ;
}
EXPORT_SYMBOL_GPL ( snd_soc_limit_volume ) ;
int snd_soc_bytes_info ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_bytes * params = ( void * ) kcontrol - > private_value ;
uinfo - > type = SNDRV_CTL_ELEM_TYPE_BYTES ;
uinfo - > count = params - > num_regs * component - > val_bytes ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_bytes_info ) ;
int snd_soc_bytes_get ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_bytes * params = ( void * ) kcontrol - > private_value ;
int ret ;
if ( component - > regmap )
ret = regmap_raw_read ( component - > regmap , params - > base ,
ucontrol - > value . bytes . data ,
params - > num_regs * component - > val_bytes ) ;
else
ret = - EINVAL ;
/* Hide any masked bytes to ensure consistent data reporting */
if ( ret = = 0 & & params - > mask ) {
switch ( component - > val_bytes ) {
case 1 :
ucontrol - > value . bytes . data [ 0 ] & = ~ params - > mask ;
break ;
case 2 :
( ( u16 * ) ( & ucontrol - > value . bytes . data ) ) [ 0 ]
& = cpu_to_be16 ( ~ params - > mask ) ;
break ;
case 4 :
( ( u32 * ) ( & ucontrol - > value . bytes . data ) ) [ 0 ]
& = cpu_to_be32 ( ~ params - > mask ) ;
break ;
default :
return - EINVAL ;
}
}
return ret ;
}
EXPORT_SYMBOL_GPL ( snd_soc_bytes_get ) ;
int snd_soc_bytes_put ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_bytes * params = ( void * ) kcontrol - > private_value ;
int ret , len ;
unsigned int val , mask ;
void * data ;
if ( ! component - > regmap | | ! params - > num_regs )
return - EINVAL ;
len = params - > num_regs * component - > val_bytes ;
data = kmemdup ( ucontrol - > value . bytes . data , len , GFP_KERNEL | GFP_DMA ) ;
if ( ! data )
return - ENOMEM ;
/*
* If we ' ve got a mask then we need to preserve the register
* bits . We shouldn ' t modify the incoming data so take a
* copy .
*/
if ( params - > mask ) {
ret = regmap_read ( component - > regmap , params - > base , & val ) ;
if ( ret ! = 0 )
goto out ;
val & = params - > mask ;
switch ( component - > val_bytes ) {
case 1 :
( ( u8 * ) data ) [ 0 ] & = ~ params - > mask ;
( ( u8 * ) data ) [ 0 ] | = val ;
break ;
case 2 :
mask = ~ params - > mask ;
ret = regmap_parse_val ( component - > regmap ,
& mask , & mask ) ;
if ( ret ! = 0 )
goto out ;
( ( u16 * ) data ) [ 0 ] & = mask ;
ret = regmap_parse_val ( component - > regmap ,
& val , & val ) ;
if ( ret ! = 0 )
goto out ;
( ( u16 * ) data ) [ 0 ] | = val ;
break ;
case 4 :
mask = ~ params - > mask ;
ret = regmap_parse_val ( component - > regmap ,
& mask , & mask ) ;
if ( ret ! = 0 )
goto out ;
( ( u32 * ) data ) [ 0 ] & = mask ;
ret = regmap_parse_val ( component - > regmap ,
& val , & val ) ;
if ( ret ! = 0 )
goto out ;
( ( u32 * ) data ) [ 0 ] | = val ;
break ;
default :
ret = - EINVAL ;
goto out ;
}
}
ret = regmap_raw_write ( component - > regmap , params - > base ,
data , len ) ;
out :
kfree ( data ) ;
return ret ;
}
EXPORT_SYMBOL_GPL ( snd_soc_bytes_put ) ;
int snd_soc_bytes_info_ext ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * ucontrol )
{
struct soc_bytes_ext * params = ( void * ) kcontrol - > private_value ;
ucontrol - > type = SNDRV_CTL_ELEM_TYPE_BYTES ;
ucontrol - > count = params - > max ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_bytes_info_ext ) ;
int snd_soc_bytes_tlv_callback ( struct snd_kcontrol * kcontrol , int op_flag ,
unsigned int size , unsigned int __user * tlv )
{
struct soc_bytes_ext * params = ( void * ) kcontrol - > private_value ;
unsigned int count = size < params - > max ? size : params - > max ;
int ret = - ENXIO ;
switch ( op_flag ) {
case SNDRV_CTL_TLV_OP_READ :
if ( params - > get )
2015-11-09 20:50:00 +03:00
ret = params - > get ( kcontrol , tlv , count ) ;
2014-10-29 01:15:31 +03:00
break ;
case SNDRV_CTL_TLV_OP_WRITE :
if ( params - > put )
2015-11-09 20:50:00 +03:00
ret = params - > put ( kcontrol , tlv , count ) ;
2014-10-29 01:15:31 +03:00
break ;
}
return ret ;
}
EXPORT_SYMBOL_GPL ( snd_soc_bytes_tlv_callback ) ;
/**
* snd_soc_info_xr_sx - signed multi register info callback
* @ kcontrol : mreg control
* @ uinfo : control element information
*
* Callback to provide information of a control that can
* span multiple codec registers which together
* forms a single signed value in a MSB / LSB manner .
*
* Returns 0 for success .
*/
int snd_soc_info_xr_sx ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo )
{
struct soc_mreg_control * mc =
( struct soc_mreg_control * ) kcontrol - > private_value ;
uinfo - > type = SNDRV_CTL_ELEM_TYPE_INTEGER ;
uinfo - > count = 1 ;
uinfo - > value . integer . min = mc - > min ;
uinfo - > value . integer . max = mc - > max ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_info_xr_sx ) ;
/**
* snd_soc_get_xr_sx - signed multi register get callback
* @ kcontrol : mreg control
* @ ucontrol : control element information
*
* Callback to get the value of a control that can span
* multiple codec registers which together forms a single
* signed value in a MSB / LSB manner . The control supports
* specifying total no of bits used to allow for bitfields
* across the multiple codec registers .
*
* Returns 0 for success .
*/
int snd_soc_get_xr_sx ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_mreg_control * mc =
( struct soc_mreg_control * ) kcontrol - > private_value ;
unsigned int regbase = mc - > regbase ;
unsigned int regcount = mc - > regcount ;
unsigned int regwshift = component - > val_bytes * BITS_PER_BYTE ;
2020-03-30 10:35:59 +03:00
unsigned int regwmask = ( 1UL < < regwshift ) - 1 ;
2014-10-29 01:15:31 +03:00
unsigned int invert = mc - > invert ;
unsigned long mask = ( 1UL < < mc - > nbits ) - 1 ;
long min = mc - > min ;
long max = mc - > max ;
long val = 0 ;
unsigned int i ;
for ( i = 0 ; i < regcount ; i + + ) {
2021-08-03 08:00:55 +03:00
unsigned int regval = snd_soc_component_read ( component , regbase + i ) ;
2014-10-29 01:15:31 +03:00
val | = ( regval & regwmask ) < < ( regwshift * ( regcount - i - 1 ) ) ;
}
val & = mask ;
if ( min < 0 & & val > max )
val | = ~ mask ;
if ( invert )
val = max - val ;
ucontrol - > value . integer . value [ 0 ] = val ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_get_xr_sx ) ;
/**
* snd_soc_put_xr_sx - signed multi register get callback
* @ kcontrol : mreg control
* @ ucontrol : control element information
*
* Callback to set the value of a control that can span
* multiple codec registers which together forms a single
* signed value in a MSB / LSB manner . The control supports
* specifying total no of bits used to allow for bitfields
* across the multiple codec registers .
*
* Returns 0 for success .
*/
int snd_soc_put_xr_sx ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_mreg_control * mc =
( struct soc_mreg_control * ) kcontrol - > private_value ;
unsigned int regbase = mc - > regbase ;
unsigned int regcount = mc - > regcount ;
unsigned int regwshift = component - > val_bytes * BITS_PER_BYTE ;
2020-03-30 10:35:59 +03:00
unsigned int regwmask = ( 1UL < < regwshift ) - 1 ;
2014-10-29 01:15:31 +03:00
unsigned int invert = mc - > invert ;
unsigned long mask = ( 1UL < < mc - > nbits ) - 1 ;
long max = mc - > max ;
long val = ucontrol - > value . integer . value [ 0 ] ;
2022-02-01 18:56:29 +03:00
int ret = 0 ;
2021-08-03 08:01:00 +03:00
unsigned int i ;
2014-10-29 01:15:31 +03:00
2022-01-24 18:32:53 +03:00
if ( val < mc - > min | | val > mc - > max )
return - EINVAL ;
2014-10-29 01:15:31 +03:00
if ( invert )
val = max - val ;
val & = mask ;
for ( i = 0 ; i < regcount ; i + + ) {
2021-08-03 08:01:00 +03:00
unsigned int regval = ( val > > ( regwshift * ( regcount - i - 1 ) ) ) & regwmask ;
unsigned int regmask = ( mask > > ( regwshift * ( regcount - i - 1 ) ) ) & regwmask ;
int err = snd_soc_component_update_bits ( component , regbase + i ,
regmask , regval ) ;
2014-10-29 01:15:31 +03:00
if ( err < 0 )
return err ;
2022-02-01 18:56:29 +03:00
if ( err > 0 )
ret = err ;
2014-10-29 01:15:31 +03:00
}
2022-02-01 18:56:29 +03:00
return ret ;
2014-10-29 01:15:31 +03:00
}
EXPORT_SYMBOL_GPL ( snd_soc_put_xr_sx ) ;
/**
* snd_soc_get_strobe - strobe get callback
* @ kcontrol : mixer control
* @ ucontrol : control element information
*
* Callback get the value of a strobe mixer control .
*
* Returns 0 for success .
*/
int snd_soc_get_strobe ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
unsigned int reg = mc - > reg ;
unsigned int shift = mc - > shift ;
unsigned int mask = 1 < < shift ;
unsigned int invert = mc - > invert ! = 0 ;
unsigned int val ;
ASoC: soc-component: merge snd_soc_component_read() and snd_soc_component_read32()
We had read/write function for Codec, Platform, etc,
but these has been merged into snd_soc_component_read/write().
Internally, it is using regmap or driver function.
In read case, each styles are like below
regmap
ret = regmap_read(..., reg, &val);
driver function
val = xxx->read(..., reg);
Because of this kind of different style, to keep same read style,
when we merged each read function into snd_soc_component_read(),
we created snd_soc_component_read32(), like below.
commit 738b49efe6c6 ("ASoC: add snd_soc_component_read32")
(1) val = snd_soc_component_read32(component, reg);
(2) ret = snd_soc_component_read(component, reg, &val);
Many drivers are using snd_soc_component_read32(), and
some drivers are using snd_soc_component_read() today.
In generally, we don't check read function successes,
because, we will have many other issues at initial timing
if read function didn't work.
Now we can use soc_component_err() when error case.
This means, it is easy to notice if error occurred.
This patch aggressively merge snd_soc_component_read() and _read32(),
and makes snd_soc_component_read/write() as generally style.
This patch do
1) merge snd_soc_component_read() and snd_soc_component_read32()
2) it uses soc_component_err() when error case (easy to notice)
3) keeps read32 for now by #define
4) update snd_soc_component_read() for all drivers
Because _read() user drivers are not too many, this patch changes
all user drivers.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
Link: https://lore.kernel.org/r/87sgev4mfl.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
2020-06-16 08:19:41 +03:00
val = snd_soc_component_read ( component , reg ) ;
2014-10-29 01:15:31 +03:00
val & = mask ;
if ( shift ! = 0 & & val ! = 0 )
val = val > > shift ;
ucontrol - > value . enumerated . item [ 0 ] = val ^ invert ;
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_soc_get_strobe ) ;
/**
* snd_soc_put_strobe - strobe put callback
* @ kcontrol : mixer control
* @ ucontrol : control element information
*
* Callback strobe a register bit to high then low ( or the inverse )
* in one pass of a single mixer enum control .
*
* Returns 1 for success .
*/
int snd_soc_put_strobe ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct snd_soc_component * component = snd_kcontrol_chip ( kcontrol ) ;
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
unsigned int reg = mc - > reg ;
unsigned int shift = mc - > shift ;
unsigned int mask = 1 < < shift ;
unsigned int invert = mc - > invert ! = 0 ;
unsigned int strobe = ucontrol - > value . enumerated . item [ 0 ] ! = 0 ;
unsigned int val1 = ( strobe ^ invert ) ? mask : 0 ;
unsigned int val2 = ( strobe ^ invert ) ? 0 : mask ;
int err ;
err = snd_soc_component_update_bits ( component , reg , mask , val1 ) ;
if ( err < 0 )
return err ;
return snd_soc_component_update_bits ( component , reg , mask , val2 ) ;
}
EXPORT_SYMBOL_GPL ( snd_soc_put_strobe ) ;