2019-05-29 07:17:59 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2015-06-11 14:11:47 +05:30
/*
* hdac - ext - bus . c - HD - audio extended core bus functions .
*
* Copyright ( C ) 2014 - 2015 Intel Corp
* Author : Jeeja KP < jeeja . kp @ intel . com >
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*
* ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
*/
# include <linux/module.h>
# include <linux/slab.h>
2015-10-13 14:57:49 +05:30
# include <linux/io.h>
2015-06-11 14:11:47 +05:30
# include <sound/hdaudio_ext.h>
MODULE_DESCRIPTION ( " HDA extended core " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
2015-06-17 11:20:18 +05:30
static void hdac_ext_writel ( u32 value , u32 __iomem * addr )
{
writel ( value , addr ) ;
}
static u32 hdac_ext_readl ( u32 __iomem * addr )
{
return readl ( addr ) ;
}
static void hdac_ext_writew ( u16 value , u16 __iomem * addr )
{
writew ( value , addr ) ;
}
static u16 hdac_ext_readw ( u16 __iomem * addr )
{
return readw ( addr ) ;
}
static void hdac_ext_writeb ( u8 value , u8 __iomem * addr )
{
writeb ( value , addr ) ;
}
static u8 hdac_ext_readb ( u8 __iomem * addr )
{
return readb ( addr ) ;
}
static const struct hdac_io_ops hdac_ext_default_io = {
. reg_writel = hdac_ext_writel ,
. reg_readl = hdac_ext_readl ,
. reg_writew = hdac_ext_writew ,
. reg_readw = hdac_ext_readw ,
. reg_writeb = hdac_ext_writeb ,
. reg_readb = hdac_ext_readb ,
} ;
2015-06-11 14:11:47 +05:30
/**
* snd_hdac_ext_bus_init - initialize a HD - audio extended bus
* @ ebus : the pointer to extended bus object
* @ dev : device pointer
* @ ops : bus verb operators
2015-06-17 11:20:18 +05:30
* @ io_ops : lowlevel I / O operators , can be NULL . If NULL core will use
* default ops
2015-06-11 14:11:47 +05:30
*
* Returns 0 if successful , or a negative error code .
*/
2018-06-01 22:53:50 -05:00
int snd_hdac_ext_bus_init ( struct hdac_bus * bus , struct device * dev ,
2015-06-11 14:11:47 +05:30
const struct hdac_bus_ops * ops ,
2018-06-01 22:53:58 -05:00
const struct hdac_io_ops * io_ops ,
const struct hdac_ext_bus_ops * ext_ops )
2015-06-11 14:11:47 +05:30
{
int ret ;
2015-06-17 11:20:18 +05:30
/* check if io ops are provided, if not load the defaults */
if ( io_ops = = NULL )
io_ops = & hdac_ext_default_io ;
2018-06-01 22:53:50 -05:00
ret = snd_hdac_bus_init ( bus , dev , ops , io_ops ) ;
2015-06-11 14:11:47 +05:30
if ( ret < 0 )
return ret ;
2018-06-01 22:53:58 -05:00
bus - > ext_ops = ext_ops ;
2019-06-17 13:36:35 +02:00
/* FIXME:
* Currently only one bus is supported , if there is device with more
* buses , bus - > idx should be greater than 0 , but there needs to be a
* reliable way to always assign same number .
*/
bus - > idx = 0 ;
2018-06-01 22:53:50 -05:00
bus - > cmd_dma_state = true ;
2016-05-12 08:58:53 +05:30
2015-06-11 14:11:47 +05:30
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_hdac_ext_bus_init ) ;
/**
* snd_hdac_ext_bus_exit - clean up a HD - audio extended bus
* @ ebus : the pointer to extended bus object
*/
2018-06-01 22:53:50 -05:00
void snd_hdac_ext_bus_exit ( struct hdac_bus * bus )
2015-06-11 14:11:47 +05:30
{
2018-06-01 22:53:50 -05:00
snd_hdac_bus_exit ( bus ) ;
WARN_ON ( ! list_empty ( & bus - > hlink_list ) ) ;
2015-06-11 14:11:47 +05:30
}
EXPORT_SYMBOL_GPL ( snd_hdac_ext_bus_exit ) ;
static void default_release ( struct device * dev )
{
snd_hdac_ext_bus_device_exit ( container_of ( dev , struct hdac_device , dev ) ) ;
}
/**
2015-08-21 15:47:41 +05:30
* snd_hdac_ext_bus_device_init - initialize the HDA extended codec base device
2015-06-11 14:11:47 +05:30
* @ ebus : hdac extended bus to attach to
* @ addr : codec address
*
* Returns zero for success or a negative error code .
*/
2018-06-01 22:53:57 -05:00
int snd_hdac_ext_bus_device_init ( struct hdac_bus * bus , int addr ,
struct hdac_device * hdev )
2015-06-11 14:11:47 +05:30
{
char name [ 15 ] ;
int ret ;
2018-06-01 22:53:49 -05:00
hdev - > bus = bus ;
2015-06-11 14:11:47 +05:30
2018-06-01 22:53:50 -05:00
snprintf ( name , sizeof ( name ) , " ehdaudio%dD%d " , bus - > idx , addr ) ;
2015-06-11 14:11:47 +05:30
ret = snd_hdac_device_init ( hdev , bus , name , addr ) ;
if ( ret < 0 ) {
dev_err ( bus - > dev , " device init failed for hdac device \n " ) ;
return ret ;
}
hdev - > type = HDA_DEV_ASOC ;
hdev - > dev . release = default_release ;
ret = snd_hdac_device_register ( hdev ) ;
if ( ret ) {
dev_err ( bus - > dev , " failed to register hdac device \n " ) ;
snd_hdac_ext_bus_device_exit ( hdev ) ;
return ret ;
}
2015-08-21 15:47:41 +05:30
2015-06-11 14:11:47 +05:30
return 0 ;
}
EXPORT_SYMBOL_GPL ( snd_hdac_ext_bus_device_init ) ;
/**
* snd_hdac_ext_bus_device_exit - clean up a HD - audio extended codec base device
* @ hdev : hdac device to clean up
*/
void snd_hdac_ext_bus_device_exit ( struct hdac_device * hdev )
{
snd_hdac_device_exit ( hdev ) ;
}
EXPORT_SYMBOL_GPL ( snd_hdac_ext_bus_device_exit ) ;
2015-08-21 15:47:40 +05:30
/**
* snd_hdac_ext_bus_device_remove - remove HD - audio extended codec base devices
*
* @ ebus : HD - audio extended bus
*/
2018-06-01 22:53:50 -05:00
void snd_hdac_ext_bus_device_remove ( struct hdac_bus * bus )
2015-08-21 15:47:40 +05:30
{
struct hdac_device * codec , * __codec ;
/*
* we need to remove all the codec devices objects created in the
* snd_hdac_ext_bus_device_init
*/
2018-06-01 22:53:50 -05:00
list_for_each_entry_safe ( codec , __codec , & bus - > codec_list , list ) {
2015-08-21 15:47:40 +05:30
snd_hdac_device_unregister ( codec ) ;
put_device ( & codec - > dev ) ;
}
}
EXPORT_SYMBOL_GPL ( snd_hdac_ext_bus_device_remove ) ;
2015-08-21 15:47:42 +05:30
# define dev_to_hdac(dev) (container_of((dev), \
struct hdac_device , dev ) )
2018-06-01 22:53:51 -05:00
static inline struct hdac_driver * get_hdrv ( struct device * dev )
2015-08-21 15:47:42 +05:30
{
struct hdac_driver * hdrv = drv_to_hdac_driver ( dev - > driver ) ;
2018-06-01 22:53:51 -05:00
return hdrv ;
2015-08-21 15:47:42 +05:30
}
2018-06-01 22:53:49 -05:00
static inline struct hdac_device * get_hdev ( struct device * dev )
2015-08-21 15:47:42 +05:30
{
struct hdac_device * hdev = dev_to_hdac_dev ( dev ) ;
2018-06-01 22:53:49 -05:00
return hdev ;
2015-08-21 15:47:42 +05:30
}
static int hda_ext_drv_probe ( struct device * dev )
{
2018-06-01 22:53:51 -05:00
return ( get_hdrv ( dev ) ) - > probe ( get_hdev ( dev ) ) ;
2015-08-21 15:47:42 +05:30
}
static int hdac_ext_drv_remove ( struct device * dev )
{
2018-06-01 22:53:51 -05:00
return ( get_hdrv ( dev ) ) - > remove ( get_hdev ( dev ) ) ;
2015-08-21 15:47:42 +05:30
}
static void hdac_ext_drv_shutdown ( struct device * dev )
{
2018-06-01 22:53:51 -05:00
return ( get_hdrv ( dev ) ) - > shutdown ( get_hdev ( dev ) ) ;
2015-08-21 15:47:42 +05:30
}
/**
* snd_hda_ext_driver_register - register a driver for ext hda devices
*
* @ drv : ext hda driver structure
*/
2018-06-01 22:53:51 -05:00
int snd_hda_ext_driver_register ( struct hdac_driver * drv )
2015-08-21 15:47:42 +05:30
{
2018-06-01 22:53:51 -05:00
drv - > type = HDA_DEV_ASOC ;
drv - > driver . bus = & snd_hda_bus_type ;
2015-08-21 15:47:42 +05:30
/* we use default match */
if ( drv - > probe )
2018-06-01 22:53:51 -05:00
drv - > driver . probe = hda_ext_drv_probe ;
2015-08-21 15:47:42 +05:30
if ( drv - > remove )
2018-06-01 22:53:51 -05:00
drv - > driver . remove = hdac_ext_drv_remove ;
2015-08-21 15:47:42 +05:30
if ( drv - > shutdown )
2018-06-01 22:53:51 -05:00
drv - > driver . shutdown = hdac_ext_drv_shutdown ;
2015-08-21 15:47:42 +05:30
2018-06-01 22:53:51 -05:00
return driver_register ( & drv - > driver ) ;
2015-08-21 15:47:42 +05:30
}
EXPORT_SYMBOL_GPL ( snd_hda_ext_driver_register ) ;
/**
* snd_hda_ext_driver_unregister - unregister a driver for ext hda devices
*
* @ drv : ext hda driver structure
*/
2018-06-01 22:53:51 -05:00
void snd_hda_ext_driver_unregister ( struct hdac_driver * drv )
2015-08-21 15:47:42 +05:30
{
2018-06-01 22:53:51 -05:00
driver_unregister ( & drv - > driver ) ;
2015-08-21 15:47:42 +05:30
}
EXPORT_SYMBOL_GPL ( snd_hda_ext_driver_unregister ) ;