2006-10-06 20:20:14 +04:00
/*
* linux / sound / soc . h - - ALSA SoC Layer
*
* Author : Liam Girdwood
* Created : Aug 11 th 2005
* Copyright : Wolfson Microelectronics . PLC .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# ifndef __LINUX_SND_SOC_H
# define __LINUX_SND_SOC_H
# include <linux/platform_device.h>
# include <linux/types.h>
2010-03-22 15:06:30 +03:00
# include <linux/notifier.h>
2006-12-15 11:30:07 +03:00
# include <linux/workqueue.h>
2009-03-04 00:25:04 +03:00
# include <linux/interrupt.h>
# include <linux/kernel.h>
2006-10-06 20:20:14 +04:00
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/control.h>
# include <sound/ac97_codec.h>
/*
* Convenience kcontrol builders
*/
2008-07-29 14:42:26 +04:00
# define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
( ( unsigned long ) & ( struct soc_mixer_control ) \
2008-10-30 15:37:08 +03:00
{ . reg = xreg , . shift = xshift , . rshift = xshift , . max = xmax , \
2010-05-10 15:39:24 +04:00
. platform_max = xmax , . invert = xinvert } )
2008-07-29 14:42:26 +04:00
# define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
( ( unsigned long ) & ( struct soc_mixer_control ) \
2010-05-10 15:39:24 +04:00
{ . reg = xreg , . max = xmax , . platform_max = xmax , . invert = xinvert } )
2008-01-10 16:37:42 +03:00
# define SOC_SINGLE(xname, reg, shift, max, invert) \
2006-10-06 20:20:14 +04:00
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , \
. info = snd_soc_info_volsw , . get = snd_soc_get_volsw , \
. put = snd_soc_put_volsw , \
2008-01-10 16:37:42 +03:00
. private_value = SOC_SINGLE_VALUE ( reg , shift , max , invert ) }
# define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , \
. access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE , \
. tlv . p = ( tlv_array ) , \
. info = snd_soc_info_volsw , . get = snd_soc_get_volsw , \
. put = snd_soc_put_volsw , \
. private_value = SOC_SINGLE_VALUE ( reg , shift , max , invert ) }
2008-07-29 14:42:26 +04:00
# define SOC_DOUBLE(xname, xreg, shift_left, shift_right, xmax, xinvert) \
2006-10-06 20:20:14 +04:00
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = ( xname ) , \
. info = snd_soc_info_volsw , . get = snd_soc_get_volsw , \
. put = snd_soc_put_volsw , \
2008-07-29 14:42:26 +04:00
. private_value = ( unsigned long ) & ( struct soc_mixer_control ) \
{ . reg = xreg , . shift = shift_left , . rshift = shift_right , \
2010-05-10 15:39:24 +04:00
. max = xmax , . platform_max = xmax , . invert = xinvert } }
2008-07-29 14:42:26 +04:00
# define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
2006-10-06 20:20:14 +04:00
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = ( xname ) , \
. info = snd_soc_info_volsw_2r , \
. get = snd_soc_get_volsw_2r , . put = snd_soc_put_volsw_2r , \
2008-07-29 14:42:26 +04:00
. private_value = ( unsigned long ) & ( struct soc_mixer_control ) \
{ . reg = reg_left , . rreg = reg_right , . shift = xshift , \
2010-05-10 15:39:24 +04:00
. max = xmax , . platform_max = xmax , . invert = xinvert } }
2008-07-29 14:42:26 +04:00
# define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \
2008-01-10 16:37:42 +03:00
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = ( xname ) , \
. access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE , \
. tlv . p = ( tlv_array ) , \
. info = snd_soc_info_volsw , . get = snd_soc_get_volsw , \
. put = snd_soc_put_volsw , \
2008-07-29 14:42:26 +04:00
. private_value = ( unsigned long ) & ( struct soc_mixer_control ) \
{ . reg = xreg , . shift = shift_left , . rshift = shift_right , \
2010-05-10 15:39:24 +04:00
. max = xmax , . platform_max = xmax , . invert = xinvert } }
2008-07-29 14:42:26 +04:00
# define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
2008-01-10 16:37:42 +03:00
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = ( xname ) , \
. access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE , \
. tlv . p = ( tlv_array ) , \
. info = snd_soc_info_volsw_2r , \
. get = snd_soc_get_volsw_2r , . put = snd_soc_put_volsw_2r , \
2008-07-29 14:42:26 +04:00
. private_value = ( unsigned long ) & ( struct soc_mixer_control ) \
{ . reg = reg_left , . rreg = reg_right , . shift = xshift , \
2010-05-10 15:39:24 +04:00
. max = xmax , . platform_max = xmax , . invert = xinvert } }
2008-07-29 14:42:26 +04:00
# define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
2008-05-28 20:58:05 +04:00
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = ( xname ) , \
. access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE , \
. tlv . p = ( tlv_array ) , \
. info = snd_soc_info_volsw_s8 , . get = snd_soc_get_volsw_s8 , \
. put = snd_soc_put_volsw_s8 , \
2008-07-29 14:42:26 +04:00
. private_value = ( unsigned long ) & ( struct soc_mixer_control ) \
2010-05-10 15:39:24 +04:00
{ . reg = xreg , . min = xmin , . max = xmax , \
. platform_max = xmax } }
2008-07-29 14:42:27 +04:00
# define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \
2006-10-06 20:20:14 +04:00
{ . reg = xreg , . shift_l = xshift_l , . shift_r = xshift_r , \
2008-07-29 14:42:27 +04:00
. max = xmax , . texts = xtexts }
# define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \
SOC_ENUM_DOUBLE ( xreg , xshift , xshift , xmax , xtexts )
# define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \
{ . max = xmax , . texts = xtexts }
2009-01-05 10:54:57 +03:00
# define SOC_VALUE_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xmax, xtexts, xvalues) \
{ . reg = xreg , . shift_l = xshift_l , . shift_r = xshift_r , \
. mask = xmask , . max = xmax , . texts = xtexts , . values = xvalues }
# define SOC_VALUE_ENUM_SINGLE(xreg, xshift, xmask, xmax, xtexts, xvalues) \
SOC_VALUE_ENUM_DOUBLE ( xreg , xshift , xshift , xmask , xmax , xtexts , xvalues )
2006-10-06 20:20:14 +04:00
# define SOC_ENUM(xname, xenum) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , \
. info = snd_soc_info_enum_double , \
. get = snd_soc_get_enum_double , . put = snd_soc_put_enum_double , \
. private_value = ( unsigned long ) & xenum }
2009-01-05 10:54:57 +03:00
# define SOC_VALUE_ENUM(xname, xenum) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , \
2009-01-08 14:34:29 +03:00
. info = snd_soc_info_enum_double , \
2009-01-05 10:54:57 +03:00
. get = snd_soc_get_value_enum_double , \
. put = snd_soc_put_value_enum_double , \
. private_value = ( unsigned long ) & xenum }
2008-07-29 14:42:27 +04:00
# define SOC_SINGLE_EXT(xname, xreg, xshift, xmax, xinvert,\
2006-10-06 20:20:14 +04:00
xhandler_get , xhandler_put ) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , \
2007-02-02 19:13:05 +03:00
. info = snd_soc_info_volsw , \
2006-10-06 20:20:14 +04:00
. get = xhandler_get , . put = xhandler_put , \
2008-07-29 14:42:27 +04:00
. private_value = SOC_SINGLE_VALUE ( xreg , xshift , xmax , xinvert ) }
2009-04-24 18:37:44 +04:00
# define SOC_DOUBLE_EXT(xname, xreg, shift_left, shift_right, xmax, xinvert,\
xhandler_get , xhandler_put ) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = ( xname ) , \
. info = snd_soc_info_volsw , \
. get = xhandler_get , . put = xhandler_put , \
. private_value = ( unsigned long ) & ( struct soc_mixer_control ) \
{ . reg = xreg , . shift = shift_left , . rshift = shift_right , \
2010-05-10 15:39:24 +04:00
. max = xmax , . platform_max = xmax , . invert = xinvert } }
2008-07-29 14:42:27 +04:00
# define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
2008-06-11 16:47:13 +04:00
xhandler_get , xhandler_put , tlv_array ) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , \
. access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE , \
. tlv . p = ( tlv_array ) , \
. info = snd_soc_info_volsw , \
. get = xhandler_get , . put = xhandler_put , \
2008-07-29 14:42:27 +04:00
. private_value = SOC_SINGLE_VALUE ( xreg , xshift , xmax , xinvert ) }
2009-07-15 15:33:47 +04:00
# define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\
xhandler_get , xhandler_put , tlv_array ) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = ( xname ) , \
. access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE , \
. tlv . p = ( tlv_array ) , \
. info = snd_soc_info_volsw , \
. get = xhandler_get , . put = xhandler_put , \
. private_value = ( unsigned long ) & ( struct soc_mixer_control ) \
{ . reg = xreg , . shift = shift_left , . rshift = shift_right , \
2010-05-10 15:39:24 +04:00
. max = xmax , . platform_max = xmax , . invert = xinvert } }
2009-07-15 15:33:50 +04:00
# define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
xhandler_get , xhandler_put , tlv_array ) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = ( xname ) , \
. access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE , \
. tlv . p = ( tlv_array ) , \
. info = snd_soc_info_volsw_2r , \
. get = xhandler_get , . put = xhandler_put , \
. private_value = ( unsigned long ) & ( struct soc_mixer_control ) \
{ . reg = reg_left , . rreg = reg_right , . shift = xshift , \
2010-05-10 15:39:24 +04:00
. max = xmax , . platform_max = xmax , . invert = xinvert } }
2006-10-06 20:20:14 +04:00
# define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , \
. info = snd_soc_info_bool_ext , \
. get = xhandler_get , . put = xhandler_put , \
. private_value = xdata }
# define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = xname , \
. info = snd_soc_info_enum_ext , \
. get = xhandler_get , . put = xhandler_put , \
. private_value = ( unsigned long ) & xenum }
2010-05-15 19:30:01 +04:00
# define SOC_DOUBLE_R_SX_TLV(xname, xreg_left, xreg_right, xshift,\
xmin , xmax , tlv_array ) \
{ . iface = SNDRV_CTL_ELEM_IFACE_MIXER , . name = ( xname ) , \
. access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE , \
. tlv . p = ( tlv_array ) , \
. info = snd_soc_info_volsw_2r_sx , \
. get = snd_soc_get_volsw_2r_sx , \
. put = snd_soc_put_volsw_2r_sx , \
. private_value = ( unsigned long ) & ( struct soc_mixer_control ) \
{ . reg = xreg_left , \
. rreg = xreg_right , . shift = xshift , \
. min = xmin , . max = xmax } }
2010-01-22 00:04:03 +03:00
/*
* Simplified versions of above macros , declaring a struct and calculating
* ARRAY_SIZE internally
*/
# define SOC_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xtexts) \
struct soc_enum name = SOC_ENUM_DOUBLE ( xreg , xshift_l , xshift_r , \
ARRAY_SIZE ( xtexts ) , xtexts )
# define SOC_ENUM_SINGLE_DECL(name, xreg, xshift, xtexts) \
SOC_ENUM_DOUBLE_DECL ( name , xreg , xshift , xshift , xtexts )
# define SOC_ENUM_SINGLE_EXT_DECL(name, xtexts) \
struct soc_enum name = SOC_ENUM_SINGLE_EXT ( ARRAY_SIZE ( xtexts ) , xtexts )
# define SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift_l, xshift_r, xmask, xtexts, xvalues) \
struct soc_enum name = SOC_VALUE_ENUM_DOUBLE ( xreg , xshift_l , xshift_r , xmask , \
ARRAY_SIZE ( xtexts ) , xtexts , xvalues )
# define SOC_VALUE_ENUM_SINGLE_DECL(name, xreg, xshift, xmask, xtexts, xvalues) \
SOC_VALUE_ENUM_DOUBLE_DECL ( name , xreg , xshift , xshift , xmask , xtexts , xvalues )
2008-05-19 14:31:28 +04:00
/*
* Bias levels
*
* @ ON : Bias is fully on for audio playback and capture operations .
* @ PREPARE : Prepare for audio operations . Called before DAPM switching for
* stream start and stop operations .
* @ STANDBY : Low power standby state when no playback / capture operations are
* in progress . NOTE : The transition time between STANDBY and ON
* should be as fast as possible and no longer than 10 ms .
* @ OFF : Power Off . No restrictions on transition times .
*/
enum snd_soc_bias_level {
SND_SOC_BIAS_OFF ,
2010-08-31 15:52:35 +04:00
SND_SOC_BIAS_STANDBY ,
SND_SOC_BIAS_PREPARE ,
SND_SOC_BIAS_ON ,
2008-05-19 14:31:28 +04:00
} ;
2009-01-07 20:31:10 +03:00
struct snd_jack ;
struct snd_soc_card ;
2006-10-06 20:20:14 +04:00
struct snd_soc_device ;
struct snd_soc_pcm_stream ;
struct snd_soc_ops ;
struct snd_soc_dai_mode ;
struct snd_soc_pcm_runtime ;
2008-07-07 19:07:17 +04:00
struct snd_soc_dai ;
2010-03-17 23:15:21 +03:00
struct snd_soc_dai_driver ;
2008-12-03 22:40:30 +03:00
struct snd_soc_platform ;
2010-02-22 09:58:04 +03:00
struct snd_soc_dai_link ;
2010-03-17 23:15:21 +03:00
struct snd_soc_platform_driver ;
2006-10-06 20:20:14 +04:00
struct snd_soc_codec ;
2010-03-17 23:15:21 +03:00
struct snd_soc_codec_driver ;
2006-10-06 20:20:14 +04:00
struct soc_enum ;
struct snd_soc_ac97_ops ;
2009-01-07 20:31:10 +03:00
struct snd_soc_jack ;
struct snd_soc_jack_pin ;
2010-03-17 23:15:21 +03:00
2009-03-04 00:25:04 +03:00
# ifdef CONFIG_GPIOLIB
struct snd_soc_jack_gpio ;
# endif
2006-10-06 20:20:14 +04:00
typedef int ( * hw_write_t ) ( void * , const char * , int ) ;
extern struct snd_ac97_bus_ops soc_ac97_ops ;
2009-07-11 01:24:27 +04:00
enum snd_soc_control_type {
SND_SOC_CUSTOM ,
SND_SOC_I2C ,
SND_SOC_SPI ,
} ;
2010-03-17 23:15:21 +03:00
int snd_soc_register_platform ( struct device * dev ,
struct snd_soc_platform_driver * platform_drv ) ;
void snd_soc_unregister_platform ( struct device * dev ) ;
int snd_soc_register_codec ( struct device * dev ,
struct snd_soc_codec_driver * codec_drv ,
struct snd_soc_dai_driver * dai_drv , int num_dai ) ;
void snd_soc_unregister_codec ( struct device * dev ) ;
2009-07-05 18:12:22 +04:00
int snd_soc_codec_volatile_register ( struct snd_soc_codec * codec , int reg ) ;
2009-07-05 20:24:50 +04:00
int snd_soc_codec_set_cache_io ( struct snd_soc_codec * codec ,
2009-07-11 01:24:27 +04:00
int addr_bits , int data_bits ,
enum snd_soc_control_type control ) ;
2008-12-03 22:40:30 +03:00
2009-11-10 19:08:04 +03:00
/* Utility functions to get clock rates from various things */
int snd_soc_calc_frame_size ( int sample_size , int channels , int tdm_slots ) ;
int snd_soc_params_to_frame_size ( struct snd_pcm_hw_params * params ) ;
2009-11-19 14:36:10 +03:00
int snd_soc_calc_bclk ( int fs , int sample_size , int channels , int tdm_slots ) ;
2009-11-10 19:08:04 +03:00
int snd_soc_params_to_bclk ( struct snd_pcm_hw_params * parms ) ;
2006-10-06 20:20:14 +04:00
/* set runtime hw params */
int snd_soc_set_runtime_hwparams ( struct snd_pcm_substream * substream ,
const struct snd_pcm_hardware * hw ) ;
2009-01-07 20:31:10 +03:00
/* Jack reporting */
2010-03-17 23:15:21 +03:00
int snd_soc_jack_new ( struct snd_soc_codec * codec , const char * id , int type ,
2009-01-07 20:31:10 +03:00
struct snd_soc_jack * jack ) ;
void snd_soc_jack_report ( struct snd_soc_jack * jack , int status , int mask ) ;
int snd_soc_jack_add_pins ( struct snd_soc_jack * jack , int count ,
struct snd_soc_jack_pin * pins ) ;
2010-03-22 15:06:30 +03:00
void snd_soc_jack_notifier_register ( struct snd_soc_jack * jack ,
struct notifier_block * nb ) ;
void snd_soc_jack_notifier_unregister ( struct snd_soc_jack * jack ,
struct notifier_block * nb ) ;
2009-03-04 00:25:04 +03:00
# ifdef CONFIG_GPIOLIB
int snd_soc_jack_add_gpios ( struct snd_soc_jack * jack , int count ,
struct snd_soc_jack_gpio * gpios ) ;
void snd_soc_jack_free_gpios ( struct snd_soc_jack * jack , int count ,
struct snd_soc_jack_gpio * gpios ) ;
# endif
2009-01-07 20:31:10 +03:00
2006-10-06 20:20:14 +04:00
/* codec register bit access */
int snd_soc_update_bits ( struct snd_soc_codec * codec , unsigned short reg ,
2009-06-07 09:49:11 +04:00
unsigned int mask , unsigned int value ) ;
2009-12-04 17:22:03 +03:00
int snd_soc_update_bits_locked ( struct snd_soc_codec * codec ,
unsigned short reg , unsigned int mask ,
unsigned int value ) ;
2006-10-06 20:20:14 +04:00
int snd_soc_test_bits ( struct snd_soc_codec * codec , unsigned short reg ,
2009-06-07 09:49:11 +04:00
unsigned int mask , unsigned int value ) ;
2006-10-06 20:20:14 +04:00
int snd_soc_new_ac97_codec ( struct snd_soc_codec * codec ,
struct snd_ac97_bus_ops * ops , int num ) ;
void snd_soc_free_ac97_codec ( struct snd_soc_codec * codec ) ;
/*
* Controls
*/
struct snd_kcontrol * snd_soc_cnew ( const struct snd_kcontrol_new * _template ,
void * data , char * long_name ) ;
2009-01-09 03:23:21 +03:00
int snd_soc_add_controls ( struct snd_soc_codec * codec ,
const struct snd_kcontrol_new * controls , int num_controls ) ;
2006-10-06 20:20:14 +04:00
int snd_soc_info_enum_double ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ) ;
int snd_soc_info_enum_ext ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ) ;
int snd_soc_get_enum_double ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_soc_put_enum_double ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
2009-01-05 10:54:57 +03:00
int snd_soc_get_value_enum_double ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_soc_put_value_enum_double ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
2006-10-06 20:20:14 +04:00
int snd_soc_info_volsw ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ) ;
int snd_soc_info_volsw_ext ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ) ;
2008-05-13 16:03:40 +04:00
# define snd_soc_info_bool_ext snd_ctl_boolean_mono_info
2006-10-06 20:20:14 +04:00
int snd_soc_get_volsw ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_soc_put_volsw ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_soc_info_volsw_2r ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ) ;
int snd_soc_get_volsw_2r ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_soc_put_volsw_2r ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
2008-05-28 20:58:05 +04:00
int snd_soc_info_volsw_s8 ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ) ;
int snd_soc_get_volsw_s8 ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_soc_put_volsw_s8 ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
2010-05-07 15:05:49 +04:00
int snd_soc_limit_volume ( struct snd_soc_codec * codec ,
const char * name , int max ) ;
2010-05-15 19:30:01 +04:00
int snd_soc_info_volsw_2r_sx ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_info * uinfo ) ;
int snd_soc_get_volsw_2r_sx ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
int snd_soc_put_volsw_2r_sx ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol ) ;
2006-10-06 20:20:14 +04:00
2009-01-07 20:31:10 +03:00
/**
* struct snd_soc_jack_pin - Describes a pin to update based on jack detection
*
* @ pin : name of the pin to update
* @ mask : bits to check for in reported jack status
* @ invert : if non - zero then pin is enabled when status is not reported
*/
struct snd_soc_jack_pin {
struct list_head list ;
const char * pin ;
int mask ;
bool invert ;
} ;
2009-03-04 00:25:04 +03:00
/**
* struct snd_soc_jack_gpio - Describes a gpio pin for jack detection
*
* @ gpio : gpio number
* @ name : gpio name
* @ report : value to report when jack detected
* @ invert : report presence in low state
* @ debouce_time : debouce time in ms
*/
# ifdef CONFIG_GPIOLIB
struct snd_soc_jack_gpio {
unsigned int gpio ;
const char * name ;
int report ;
int invert ;
int debounce_time ;
struct snd_soc_jack * jack ;
struct work_struct work ;
2009-11-12 11:14:04 +03:00
int ( * jack_status_check ) ( void ) ;
2009-03-04 00:25:04 +03:00
} ;
# endif
2009-01-07 20:31:10 +03:00
struct snd_soc_jack {
struct snd_jack * jack ;
2010-03-17 23:15:21 +03:00
struct snd_soc_codec * codec ;
2009-01-07 20:31:10 +03:00
struct list_head pins ;
int status ;
2010-03-22 15:06:30 +03:00
struct blocking_notifier_head notifier ;
2009-01-07 20:31:10 +03:00
} ;
2006-10-06 20:20:14 +04:00
/* SoC PCM stream information */
struct snd_soc_pcm_stream {
2010-03-17 23:15:21 +03:00
const char * stream_name ;
2007-02-02 19:13:05 +03:00
u64 formats ; /* SNDRV_PCM_FMTBIT_* */
unsigned int rates ; /* SNDRV_PCM_RATE_* */
2006-10-06 20:20:14 +04:00
unsigned int rate_min ; /* min rate */
unsigned int rate_max ; /* max rate */
unsigned int channels_min ; /* min channels */
unsigned int channels_max ; /* max channels */
} ;
/* SoC audio ops */
struct snd_soc_ops {
int ( * startup ) ( struct snd_pcm_substream * ) ;
void ( * shutdown ) ( struct snd_pcm_substream * ) ;
int ( * hw_params ) ( struct snd_pcm_substream * , struct snd_pcm_hw_params * ) ;
int ( * hw_free ) ( struct snd_pcm_substream * ) ;
int ( * prepare ) ( struct snd_pcm_substream * ) ;
int ( * trigger ) ( struct snd_pcm_substream * , int ) ;
} ;
2010-03-17 23:15:21 +03:00
/* SoC Audio Codec device */
2006-10-06 20:20:14 +04:00
struct snd_soc_codec {
2010-03-17 23:15:21 +03:00
const char * name ;
int id ;
2008-12-10 17:32:45 +03:00
struct device * dev ;
2010-03-17 23:15:21 +03:00
struct snd_soc_codec_driver * driver ;
2008-12-10 17:32:45 +03:00
2010-03-17 23:15:21 +03:00
struct mutex mutex ;
struct snd_soc_card * card ;
2008-12-10 17:32:45 +03:00
struct list_head list ;
2010-03-17 23:15:21 +03:00
struct list_head card_list ;
int num_dai ;
2006-10-06 20:20:14 +04:00
/* runtime */
struct snd_ac97 * ac97 ; /* for ad-hoc ac97 devices */
unsigned int active ;
2010-03-17 23:15:21 +03:00
unsigned int idle_bias_off : 1 ; /* Use BIAS_OFF instead of STANDBY */
unsigned int cache_only : 1 ; /* Suppress writes to hardware */
unsigned int cache_sync : 1 ; /* Cache needs to be synced to hardware */
unsigned int suspended : 1 ; /* Codec is in suspend PM state */
unsigned int probed : 1 ; /* Codec has been probed */
unsigned int ac97_registered : 1 ; /* Codec has been AC97 registered */
unsigned int sysfs_registered : 1 ; /* codec has been sysfs registered */
2006-10-06 20:20:14 +04:00
/* codec IO */
void * control_data ; /* codec control (i2c/3wire) data */
hw_write_t hw_write ;
2009-07-11 02:11:24 +04:00
unsigned int ( * hw_read ) ( struct snd_soc_codec * , unsigned int ) ;
2006-10-06 20:20:14 +04:00
void * reg_cache ;
2010-01-20 01:49:43 +03:00
2006-10-06 20:20:14 +04:00
/* dapm */
2008-10-14 04:42:14 +04:00
u32 pop_time ;
2006-10-06 20:20:14 +04:00
struct list_head dapm_widgets ;
struct list_head dapm_paths ;
2008-05-19 14:31:28 +04:00
enum snd_soc_bias_level bias_level ;
enum snd_soc_bias_level suspend_bias_level ;
2006-12-21 13:02:06 +03:00
struct delayed_work delayed_work ;
2006-10-06 20:20:14 +04:00
2008-12-03 20:34:03 +03:00
# ifdef CONFIG_DEBUG_FS
2009-10-01 11:32:47 +04:00
struct dentry * debugfs_codec_root ;
2008-12-03 20:34:03 +03:00
struct dentry * debugfs_reg ;
struct dentry * debugfs_pop_time ;
2009-08-21 19:38:13 +04:00
struct dentry * debugfs_dapm ;
2008-12-03 20:34:03 +03:00
# endif
2006-10-06 20:20:14 +04:00
} ;
2010-03-17 23:15:21 +03:00
/* codec driver */
struct snd_soc_codec_driver {
/* driver ops */
int ( * probe ) ( struct snd_soc_codec * ) ;
int ( * remove ) ( struct snd_soc_codec * ) ;
int ( * suspend ) ( struct snd_soc_codec * ,
pm_message_t state ) ;
int ( * resume ) ( struct snd_soc_codec * ) ;
/* codec IO */
unsigned int ( * read ) ( struct snd_soc_codec * , unsigned int ) ;
int ( * write ) ( struct snd_soc_codec * , unsigned int , unsigned int ) ;
int ( * display_register ) ( struct snd_soc_codec * , char * ,
size_t , unsigned int ) ;
int ( * volatile_register ) ( unsigned int ) ;
int ( * readable_register ) ( unsigned int ) ;
short reg_cache_size ;
short reg_cache_step ;
short reg_word_size ;
const void * reg_cache_default ;
/* codec bias level */
int ( * set_bias_level ) ( struct snd_soc_codec * ,
enum snd_soc_bias_level level ) ;
2006-10-06 20:20:14 +04:00
} ;
/* SoC platform interface */
2010-03-17 23:15:21 +03:00
struct snd_soc_platform_driver {
2006-10-06 20:20:14 +04:00
2010-03-17 23:15:21 +03:00
int ( * probe ) ( struct snd_soc_platform * ) ;
int ( * remove ) ( struct snd_soc_platform * ) ;
int ( * suspend ) ( struct snd_soc_dai * dai ) ;
int ( * resume ) ( struct snd_soc_dai * dai ) ;
2006-10-06 20:20:14 +04:00
/* pcm creation and destruction */
2008-07-07 19:07:17 +04:00
int ( * pcm_new ) ( struct snd_card * , struct snd_soc_dai * ,
2006-10-06 20:20:14 +04:00
struct snd_pcm * ) ;
void ( * pcm_free ) ( struct snd_pcm * ) ;
2010-03-03 16:08:07 +03:00
/*
* For platform caused delay reporting .
* Optional .
*/
snd_pcm_sframes_t ( * delay ) ( struct snd_pcm_substream * ,
struct snd_soc_dai * ) ;
2006-10-06 20:20:14 +04:00
/* platform stream ops */
2010-03-17 23:15:21 +03:00
struct snd_pcm_ops * ops ;
2006-10-06 20:20:14 +04:00
} ;
2010-03-17 23:15:21 +03:00
struct snd_soc_platform {
const char * name ;
int id ;
struct device * dev ;
struct snd_soc_platform_driver * driver ;
2006-10-06 20:20:14 +04:00
2010-03-17 23:15:21 +03:00
unsigned int suspended : 1 ; /* platform is suspended */
unsigned int probed : 1 ;
2007-02-02 19:13:05 +03:00
2010-03-17 23:15:21 +03:00
struct snd_soc_card * card ;
struct list_head list ;
struct list_head card_list ;
} ;
2006-10-06 20:20:14 +04:00
2010-03-17 23:15:21 +03:00
struct snd_soc_dai_link {
/* config - must be set by machine driver */
const char * name ; /* Codec name */
const char * stream_name ; /* Stream name */
const char * codec_name ; /* for multi-codec */
const char * platform_name ; /* for multi-platform */
const char * cpu_dai_name ;
const char * codec_dai_name ;
2008-01-10 16:39:01 +03:00
2010-05-09 16:25:43 +04:00
/* Keep DAI active over suspend */
unsigned int ignore_suspend : 1 ;
2009-04-07 21:10:13 +04:00
/* Symmetry requirements */
unsigned int symmetric_rates : 1 ;
2010-03-17 23:15:21 +03:00
/* codec/machine specific init - e.g. add machine controls */
int ( * init ) ( struct snd_soc_pcm_runtime * rtd ) ;
2009-04-07 21:10:13 +04:00
2010-03-17 23:15:21 +03:00
/* machine stream operations */
struct snd_soc_ops * ops ;
2006-10-06 20:20:14 +04:00
} ;
2008-11-18 23:50:34 +03:00
/* SoC card */
struct snd_soc_card {
2010-03-17 23:15:21 +03:00
const char * name ;
2008-11-28 16:29:45 +03:00
struct device * dev ;
2010-03-17 23:15:21 +03:00
struct snd_card * snd_card ;
struct module * owner ;
2008-11-28 16:29:45 +03:00
struct list_head list ;
2010-03-17 23:15:21 +03:00
struct mutex mutex ;
2008-11-28 16:29:45 +03:00
2010-03-17 23:15:21 +03:00
bool instantiated ;
2006-10-06 20:20:14 +04:00
int ( * probe ) ( struct platform_device * pdev ) ;
int ( * remove ) ( struct platform_device * pdev ) ;
/* the pre and post PM functions are used to do any PM work before and
* after the codec and DAI ' s do any PM work . */
int ( * suspend_pre ) ( struct platform_device * pdev , pm_message_t state ) ;
int ( * suspend_post ) ( struct platform_device * pdev , pm_message_t state ) ;
int ( * resume_pre ) ( struct platform_device * pdev ) ;
int ( * resume_post ) ( struct platform_device * pdev ) ;
2008-01-10 16:36:20 +03:00
/* callbacks */
2008-11-18 23:50:34 +03:00
int ( * set_bias_level ) ( struct snd_soc_card * ,
2008-05-19 14:31:28 +04:00
enum snd_soc_bias_level level ) ;
2008-01-10 16:36:20 +03:00
2010-02-17 17:30:44 +03:00
long pmdown_time ;
2010-02-12 14:05:44 +03:00
2006-10-06 20:20:14 +04:00
/* CPU <--> Codec DAI links */
struct snd_soc_dai_link * dai_link ;
int num_links ;
2010-03-17 23:15:21 +03:00
struct snd_soc_pcm_runtime * rtd ;
int num_rtd ;
2008-12-02 18:08:03 +03:00
struct work_struct deferred_resume_work ;
2010-03-17 23:15:21 +03:00
/* lists of probed devices belonging to this card */
struct list_head codec_dev_list ;
struct list_head platform_dev_list ;
struct list_head dai_dev_list ;
2006-10-06 20:20:14 +04:00
} ;
2010-03-17 23:15:21 +03:00
/* SoC machine DAI configuration, glues a codec and cpu DAI together */
struct snd_soc_pcm_runtime {
struct device dev ;
2008-11-18 23:50:34 +03:00
struct snd_soc_card * card ;
2010-03-17 23:15:21 +03:00
struct snd_soc_dai_link * dai_link ;
unsigned int complete : 1 ;
unsigned int dev_registered : 1 ;
2006-10-06 20:20:14 +04:00
2010-03-17 23:15:21 +03:00
/* Symmetry data - only valid if symmetry is being enforced */
unsigned int rate ;
long pmdown_time ;
/* runtime devices */
struct snd_pcm * pcm ;
struct snd_soc_codec * codec ;
struct snd_soc_platform * platform ;
struct snd_soc_dai * codec_dai ;
struct snd_soc_dai * cpu_dai ;
struct delayed_work delayed_work ;
2006-10-06 20:20:14 +04:00
} ;
2008-07-29 14:42:26 +04:00
/* mixer control */
struct soc_mixer_control {
2010-05-10 15:39:24 +04:00
int min , max , platform_max ;
2008-07-29 18:22:24 +04:00
unsigned int reg , rreg , shift , rshift , invert ;
2008-07-29 14:42:26 +04:00
} ;
2006-10-06 20:20:14 +04:00
/* enumerated kcontrol */
struct soc_enum {
2009-01-05 10:54:57 +03:00
unsigned short reg ;
unsigned short reg2 ;
unsigned char shift_l ;
unsigned char shift_r ;
unsigned int max ;
unsigned int mask ;
const char * * texts ;
const unsigned int * values ;
void * dapm ;
} ;
2009-05-22 12:41:30 +04:00
/* codec IO */
static inline unsigned int snd_soc_read ( struct snd_soc_codec * codec ,
unsigned int reg )
{
2010-03-17 23:15:21 +03:00
return codec - > driver - > read ( codec , reg ) ;
2009-05-22 12:41:30 +04:00
}
static inline unsigned int snd_soc_write ( struct snd_soc_codec * codec ,
unsigned int reg , unsigned int val )
{
2010-03-17 23:15:21 +03:00
return codec - > driver - > write ( codec , reg , val ) ;
2009-05-22 12:41:30 +04:00
}
2010-03-17 23:15:21 +03:00
/* device driver data */
2010-04-14 10:35:19 +04:00
static inline void snd_soc_codec_set_drvdata ( struct snd_soc_codec * codec ,
2010-03-17 23:15:21 +03:00
void * data )
2010-04-14 10:35:19 +04:00
{
2010-03-17 23:15:21 +03:00
dev_set_drvdata ( codec - > dev , data ) ;
2010-04-14 10:35:19 +04:00
}
static inline void * snd_soc_codec_get_drvdata ( struct snd_soc_codec * codec )
{
2010-03-17 23:15:21 +03:00
return dev_get_drvdata ( codec - > dev ) ;
}
static inline void snd_soc_platform_set_drvdata ( struct snd_soc_platform * platform ,
void * data )
{
dev_set_drvdata ( platform - > dev , data ) ;
}
static inline void * snd_soc_platform_get_drvdata ( struct snd_soc_platform * platform )
{
return dev_get_drvdata ( platform - > dev ) ;
}
static inline void snd_soc_pcm_set_drvdata ( struct snd_soc_pcm_runtime * rtd ,
void * data )
{
dev_set_drvdata ( & rtd - > dev , data ) ;
}
static inline void * snd_soc_pcm_get_drvdata ( struct snd_soc_pcm_runtime * rtd )
{
return dev_get_drvdata ( & rtd - > dev ) ;
2010-04-14 10:35:19 +04:00
}
2008-07-23 17:03:07 +04:00
# include <sound/soc-dai.h>
2006-10-06 20:20:14 +04:00
# endif