2019-05-29 07:17:58 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2015-03-03 16:21:55 -08:00
/*
* Copyright ( c ) 2010 - 2011 , 2013 - 2015 The Linux Foundation . All rights reserved .
*
* lpass - platform . c - - ALSA SoC platform driver for QTi LPASS
*/
# include <linux/dma-mapping.h>
# include <linux/export.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <sound/pcm_params.h>
# include <linux/regmap.h>
# include <sound/soc.h>
2015-05-16 13:32:17 +01:00
# include "lpass-lpaif-reg.h"
2015-03-03 16:21:55 -08:00
# include "lpass.h"
2018-01-29 02:48:52 +00:00
# define DRV_NAME "lpass-platform"
2015-05-16 13:32:34 +01:00
struct lpass_pcm_data {
2016-10-31 11:25:44 +00:00
int dma_ch ;
2015-05-16 13:32:34 +01:00
int i2s_port ;
} ;
2020-10-08 10:47:02 +05:30
# define LPASS_PLATFORM_BUFFER_SIZE (24 * 2 * 1024)
2015-03-03 16:21:55 -08:00
# define LPASS_PLATFORM_PERIODS 2
2017-08-17 15:46:12 +05:30
static const struct snd_pcm_hardware lpass_platform_pcm_hardware = {
2015-03-03 16:21:55 -08:00
. info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE |
SNDRV_PCM_INFO_RESUME ,
. formats = SNDRV_PCM_FMTBIT_S16 |
SNDRV_PCM_FMTBIT_S24 |
SNDRV_PCM_FMTBIT_S32 ,
. rates = SNDRV_PCM_RATE_8000_192000 ,
. rate_min = 8000 ,
. rate_max = 192000 ,
. channels_min = 1 ,
. channels_max = 8 ,
. buffer_bytes_max = LPASS_PLATFORM_BUFFER_SIZE ,
. period_bytes_max = LPASS_PLATFORM_BUFFER_SIZE /
LPASS_PLATFORM_PERIODS ,
. period_bytes_min = LPASS_PLATFORM_BUFFER_SIZE /
LPASS_PLATFORM_PERIODS ,
. periods_min = LPASS_PLATFORM_PERIODS ,
. periods_max = LPASS_PLATFORM_PERIODS ,
. fifo_size = 0 ,
} ;
2020-08-14 16:23:01 +05:30
static int lpass_platform_alloc_dmactl_fields ( struct device * dev ,
struct regmap * map )
{
struct lpass_data * drvdata = dev_get_drvdata ( dev ) ;
struct lpass_variant * v = drvdata - > variant ;
struct lpaif_dmactl * rd_dmactl , * wr_dmactl ;
2020-09-25 17:48:56 +01:00
int rval ;
2020-08-14 16:23:01 +05:30
drvdata - > rd_dmactl = devm_kzalloc ( dev , sizeof ( struct lpaif_dmactl ) ,
GFP_KERNEL ) ;
if ( drvdata - > rd_dmactl = = NULL )
return - ENOMEM ;
drvdata - > wr_dmactl = devm_kzalloc ( dev , sizeof ( struct lpaif_dmactl ) ,
GFP_KERNEL ) ;
if ( drvdata - > wr_dmactl = = NULL )
return - ENOMEM ;
rd_dmactl = drvdata - > rd_dmactl ;
wr_dmactl = drvdata - > wr_dmactl ;
2020-10-08 10:47:00 +05:30
rval = devm_regmap_field_bulk_alloc ( dev , map , & rd_dmactl - > intf ,
& v - > rdma_intf , 6 ) ;
2020-09-25 17:48:56 +01:00
if ( rval )
return rval ;
2020-08-14 16:23:01 +05:30
2020-10-08 10:47:00 +05:30
return devm_regmap_field_bulk_alloc ( dev , map , & wr_dmactl - > intf ,
& v - > wrdma_intf , 6 ) ;
2020-08-14 16:23:01 +05:30
}
2020-10-08 10:47:01 +05:30
static int lpass_platform_alloc_hdmidmactl_fields ( struct device * dev ,
struct regmap * map )
{
struct lpass_data * drvdata = dev_get_drvdata ( dev ) ;
struct lpass_variant * v = drvdata - > variant ;
struct lpaif_dmactl * rd_dmactl ;
rd_dmactl = devm_kzalloc ( dev , sizeof ( struct lpaif_dmactl ) , GFP_KERNEL ) ;
if ( rd_dmactl = = NULL )
return - ENOMEM ;
drvdata - > hdmi_rd_dmactl = rd_dmactl ;
return devm_regmap_field_bulk_alloc ( dev , map , & rd_dmactl - > bursten ,
& v - > hdmi_rdma_bursten , 8 ) ;
}
2019-10-02 14:33:29 +09:00
static int lpass_platform_pcmops_open ( struct snd_soc_component * component ,
struct snd_pcm_substream * substream )
2015-03-03 16:21:55 -08:00
{
struct snd_pcm_runtime * runtime = substream - > runtime ;
2020-07-20 10:19:00 +09:00
struct snd_soc_pcm_runtime * soc_runtime = asoc_substream_to_rtd ( substream ) ;
2020-03-23 14:20:01 +09:00
struct snd_soc_dai * cpu_dai = asoc_rtd_to_cpu ( soc_runtime , 0 ) ;
2018-01-29 02:48:52 +00:00
struct lpass_data * drvdata = snd_soc_component_get_drvdata ( component ) ;
2016-10-31 11:25:43 +00:00
struct lpass_variant * v = drvdata - > variant ;
int ret , dma_ch , dir = substream - > stream ;
struct lpass_pcm_data * data ;
2020-10-08 10:47:01 +05:30
struct regmap * map ;
unsigned int dai_id = cpu_dai - > driver - > id ;
2016-10-31 11:25:43 +00:00
2020-11-23 21:47:53 +05:30
component - > id = dai_id ;
2020-08-14 16:23:00 +05:30
data = kzalloc ( sizeof ( * data ) , GFP_KERNEL ) ;
2016-10-31 11:25:43 +00:00
if ( ! data )
return - ENOMEM ;
data - > i2s_port = cpu_dai - > driver - > id ;
runtime - > private_data = data ;
if ( v - > alloc_dma_channel )
2020-10-08 10:47:01 +05:30
dma_ch = v - > alloc_dma_channel ( drvdata , dir , dai_id ) ;
2016-11-08 14:38:52 +01:00
else
dma_ch = 0 ;
2020-11-15 10:26:50 +05:30
if ( dma_ch < 0 ) {
kfree ( data ) ;
2016-10-31 11:25:43 +00:00
return dma_ch ;
2020-11-15 10:26:50 +05:30
}
2016-10-31 11:25:43 +00:00
2020-10-08 10:47:01 +05:30
if ( cpu_dai - > driver - > id = = LPASS_DP_RX ) {
map = drvdata - > hdmiif_map ;
drvdata - > hdmi_substream [ dma_ch ] = substream ;
} else {
map = drvdata - > lpaif_map ;
drvdata - > substream [ dma_ch ] = substream ;
}
data - > dma_ch = dma_ch ;
ret = regmap_write ( map ,
LPAIF_DMACTL_REG ( v , dma_ch , dir , data - > i2s_port ) , 0 ) ;
2016-10-31 11:25:43 +00:00
if ( ret ) {
dev_err ( soc_runtime - > dev ,
2017-01-30 13:03:37 -08:00
" error writing to rdmactl reg: %d \n " , ret ) ;
2018-11-16 15:06:36 +00:00
return ret ;
2016-10-31 11:25:43 +00:00
}
2015-03-03 16:21:55 -08:00
snd_soc_set_runtime_hwparams ( substream , & lpass_platform_pcm_hardware ) ;
runtime - > dma_bytes = lpass_platform_pcm_hardware . buffer_bytes_max ;
ret = snd_pcm_hw_constraint_integer ( runtime ,
SNDRV_PCM_HW_PARAM_PERIODS ) ;
if ( ret < 0 ) {
2020-11-15 10:26:50 +05:30
kfree ( data ) ;
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev , " setting constraints failed: %d \n " ,
ret ) ;
2015-03-03 16:21:55 -08:00
return - EINVAL ;
}
snd_pcm_set_runtime_buffer ( substream , & substream - > dma_buffer ) ;
return 0 ;
}
2019-10-02 14:33:29 +09:00
static int lpass_platform_pcmops_close ( struct snd_soc_component * component ,
struct snd_pcm_substream * substream )
2016-10-31 11:25:43 +00:00
{
struct snd_pcm_runtime * runtime = substream - > runtime ;
2020-10-08 10:47:01 +05:30
struct snd_soc_pcm_runtime * soc_runtime = asoc_substream_to_rtd ( substream ) ;
struct snd_soc_dai * cpu_dai = asoc_rtd_to_cpu ( soc_runtime , 0 ) ;
2018-01-29 02:48:52 +00:00
struct lpass_data * drvdata = snd_soc_component_get_drvdata ( component ) ;
2016-10-31 11:25:43 +00:00
struct lpass_variant * v = drvdata - > variant ;
struct lpass_pcm_data * data ;
2020-10-08 10:47:01 +05:30
unsigned int dai_id = cpu_dai - > driver - > id ;
2016-10-31 11:25:43 +00:00
data = runtime - > private_data ;
2020-10-08 10:47:01 +05:30
if ( dai_id = = LPASS_DP_RX )
drvdata - > hdmi_substream [ data - > dma_ch ] = NULL ;
else
drvdata - > substream [ data - > dma_ch ] = NULL ;
2016-10-31 11:25:43 +00:00
if ( v - > free_dma_channel )
2020-10-08 10:47:01 +05:30
v - > free_dma_channel ( drvdata , data - > dma_ch , dai_id ) ;
2016-10-31 11:25:43 +00:00
2020-08-14 16:23:00 +05:30
kfree ( data ) ;
2016-10-31 11:25:43 +00:00
return 0 ;
}
2019-10-02 14:33:29 +09:00
static int lpass_platform_pcmops_hw_params ( struct snd_soc_component * component ,
struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params )
2015-03-03 16:21:55 -08:00
{
2020-07-20 10:19:00 +09:00
struct snd_soc_pcm_runtime * soc_runtime = asoc_substream_to_rtd ( substream ) ;
2020-10-08 10:47:01 +05:30
struct snd_soc_dai * cpu_dai = asoc_rtd_to_cpu ( soc_runtime , 0 ) ;
2018-01-29 02:48:52 +00:00
struct lpass_data * drvdata = snd_soc_component_get_drvdata ( component ) ;
2016-10-31 11:25:43 +00:00
struct snd_pcm_runtime * rt = substream - > runtime ;
struct lpass_pcm_data * pcm_data = rt - > private_data ;
2015-05-16 13:32:17 +01:00
struct lpass_variant * v = drvdata - > variant ;
2015-03-03 16:21:55 -08:00
snd_pcm_format_t format = params_format ( params ) ;
unsigned int channels = params_channels ( params ) ;
unsigned int regval ;
2020-08-14 16:23:01 +05:30
struct lpaif_dmactl * dmactl ;
int id , dir = substream - > stream ;
2015-03-03 16:21:55 -08:00
int bitwidth ;
2016-02-11 12:17:30 +00:00
int ret , dma_port = pcm_data - > i2s_port + v - > dmactl_audif_start ;
2020-10-08 10:47:01 +05:30
unsigned int dai_id = cpu_dai - > driver - > id ;
2015-03-03 16:21:55 -08:00
2020-08-14 16:23:01 +05:30
if ( dir = = SNDRV_PCM_STREAM_PLAYBACK ) {
id = pcm_data - > dma_ch ;
2020-10-08 10:47:01 +05:30
if ( dai_id = = LPASS_DP_RX )
dmactl = drvdata - > hdmi_rd_dmactl ;
else
dmactl = drvdata - > rd_dmactl ;
2020-08-14 16:23:01 +05:30
} else {
dmactl = drvdata - > wr_dmactl ;
id = pcm_data - > dma_ch - v - > wrdma_channel_start ;
}
2016-02-11 12:18:33 +00:00
2015-03-03 16:21:55 -08:00
bitwidth = snd_pcm_format_width ( format ) ;
if ( bitwidth < 0 ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev , " invalid bit width given: %d \n " ,
bitwidth ) ;
2015-03-03 16:21:55 -08:00
return bitwidth ;
}
2020-08-14 16:23:01 +05:30
ret = regmap_fields_write ( dmactl - > bursten , id , LPAIF_DMACTL_BURSTEN_INCR4 ) ;
if ( ret ) {
dev_err ( soc_runtime - > dev , " error updating bursten field: %d \n " , ret ) ;
return ret ;
}
2020-10-08 10:47:01 +05:30
ret = regmap_fields_write ( dmactl - > fifowm , id , LPAIF_DMACTL_FIFOWM_8 ) ;
2020-08-14 16:23:01 +05:30
if ( ret ) {
dev_err ( soc_runtime - > dev , " error updating fifowm field: %d \n " , ret ) ;
return ret ;
}
2020-10-08 10:47:01 +05:30
switch ( dai_id ) {
case LPASS_DP_RX :
ret = regmap_fields_write ( dmactl - > burst8 , id ,
LPAIF_DMACTL_BURSTEN_INCR4 ) ;
if ( ret ) {
dev_err ( soc_runtime - > dev , " error updating burst8en field: %d \n " , ret ) ;
return ret ;
}
ret = regmap_fields_write ( dmactl - > burst16 , id ,
LPAIF_DMACTL_BURSTEN_INCR4 ) ;
if ( ret ) {
dev_err ( soc_runtime - > dev , " error updating burst16en field: %d \n " , ret ) ;
return ret ;
}
ret = regmap_fields_write ( dmactl - > dynburst , id ,
LPAIF_DMACTL_BURSTEN_INCR4 ) ;
if ( ret ) {
dev_err ( soc_runtime - > dev , " error updating dynbursten field: %d \n " , ret ) ;
return ret ;
}
break ;
case MI2S_PRIMARY :
case MI2S_SECONDARY :
2021-01-19 17:15:27 +00:00
case MI2S_TERTIARY :
case MI2S_QUATERNARY :
case MI2S_QUINARY :
2020-10-08 10:47:01 +05:30
ret = regmap_fields_write ( dmactl - > intf , id ,
LPAIF_DMACTL_AUDINTF ( dma_port ) ) ;
if ( ret ) {
dev_err ( soc_runtime - > dev , " error updating audio interface field: %d \n " ,
ret ) ;
return ret ;
}
2015-03-03 16:21:55 -08:00
2020-10-08 10:47:01 +05:30
break ;
default :
dev_err ( soc_runtime - > dev , " %s: invalid interface: %d \n " , __func__ , dai_id ) ;
break ;
}
2015-03-03 16:21:55 -08:00
switch ( bitwidth ) {
case 16 :
switch ( channels ) {
case 1 :
case 2 :
2020-08-14 16:23:01 +05:30
regval = LPAIF_DMACTL_WPSCNT_ONE ;
2015-03-03 16:21:55 -08:00
break ;
case 4 :
2020-08-14 16:23:01 +05:30
regval = LPAIF_DMACTL_WPSCNT_TWO ;
2015-03-03 16:21:55 -08:00
break ;
case 6 :
2020-08-14 16:23:01 +05:30
regval = LPAIF_DMACTL_WPSCNT_THREE ;
2015-03-03 16:21:55 -08:00
break ;
case 8 :
2020-08-14 16:23:01 +05:30
regval = LPAIF_DMACTL_WPSCNT_FOUR ;
2015-03-03 16:21:55 -08:00
break ;
default :
2020-10-08 10:47:01 +05:30
dev_err ( soc_runtime - > dev , " invalid PCM config given: bw=%d, ch=%u \n " ,
2017-01-30 13:03:37 -08:00
bitwidth , channels ) ;
2015-03-03 16:21:55 -08:00
return - EINVAL ;
}
break ;
case 24 :
case 32 :
switch ( channels ) {
case 1 :
2020-08-14 16:23:01 +05:30
regval = LPAIF_DMACTL_WPSCNT_ONE ;
2015-03-03 16:21:55 -08:00
break ;
case 2 :
2020-10-08 10:47:01 +05:30
regval = ( dai_id = = LPASS_DP_RX ?
LPAIF_DMACTL_WPSCNT_ONE :
LPAIF_DMACTL_WPSCNT_TWO ) ;
2015-03-03 16:21:55 -08:00
break ;
case 4 :
2020-10-08 10:47:01 +05:30
regval = ( dai_id = = LPASS_DP_RX ?
LPAIF_DMACTL_WPSCNT_TWO :
LPAIF_DMACTL_WPSCNT_FOUR ) ;
2015-03-03 16:21:55 -08:00
break ;
case 6 :
2020-10-08 10:47:01 +05:30
regval = ( dai_id = = LPASS_DP_RX ?
LPAIF_DMACTL_WPSCNT_THREE :
LPAIF_DMACTL_WPSCNT_SIX ) ;
2015-03-03 16:21:55 -08:00
break ;
case 8 :
2020-10-08 10:47:01 +05:30
regval = ( dai_id = = LPASS_DP_RX ?
LPAIF_DMACTL_WPSCNT_FOUR :
LPAIF_DMACTL_WPSCNT_EIGHT ) ;
2015-03-03 16:21:55 -08:00
break ;
default :
2020-10-08 10:47:01 +05:30
dev_err ( soc_runtime - > dev , " invalid PCM config given: bw=%d, ch=%u \n " ,
2017-01-30 13:03:37 -08:00
bitwidth , channels ) ;
2015-03-03 16:21:55 -08:00
return - EINVAL ;
}
break ;
default :
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev , " invalid PCM config given: bw=%d, ch=%u \n " ,
bitwidth , channels ) ;
2015-03-03 16:21:55 -08:00
return - EINVAL ;
}
2020-08-14 16:23:01 +05:30
ret = regmap_fields_write ( dmactl - > wpscnt , id , regval ) ;
2015-03-03 16:21:55 -08:00
if ( ret ) {
2020-08-14 16:23:01 +05:30
dev_err ( soc_runtime - > dev , " error writing to dmactl reg: %d \n " ,
2017-01-30 13:03:37 -08:00
ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
return 0 ;
}
2019-10-02 14:33:29 +09:00
static int lpass_platform_pcmops_hw_free ( struct snd_soc_component * component ,
struct snd_pcm_substream * substream )
2015-03-03 16:21:55 -08:00
{
2020-07-20 10:19:00 +09:00
struct snd_soc_pcm_runtime * soc_runtime = asoc_substream_to_rtd ( substream ) ;
2020-10-08 10:47:01 +05:30
struct snd_soc_dai * cpu_dai = asoc_rtd_to_cpu ( soc_runtime , 0 ) ;
2018-01-29 02:48:52 +00:00
struct lpass_data * drvdata = snd_soc_component_get_drvdata ( component ) ;
2016-10-31 11:25:43 +00:00
struct snd_pcm_runtime * rt = substream - > runtime ;
struct lpass_pcm_data * pcm_data = rt - > private_data ;
2015-05-16 13:32:17 +01:00
struct lpass_variant * v = drvdata - > variant ;
2016-02-11 12:18:33 +00:00
unsigned int reg ;
2015-03-03 16:21:55 -08:00
int ret ;
2020-10-08 10:47:01 +05:30
struct regmap * map ;
unsigned int dai_id = cpu_dai - > driver - > id ;
2015-03-03 16:21:55 -08:00
2020-10-08 10:47:01 +05:30
if ( dai_id = = LPASS_DP_RX )
map = drvdata - > hdmiif_map ;
else
map = drvdata - > lpaif_map ;
reg = LPAIF_DMACTL_REG ( v , pcm_data - > dma_ch , substream - > stream , dai_id ) ;
ret = regmap_write ( map , reg , 0 ) ;
2015-03-03 16:21:55 -08:00
if ( ret )
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev , " error writing to rdmactl reg: %d \n " ,
ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
2019-10-02 14:33:29 +09:00
static int lpass_platform_pcmops_prepare ( struct snd_soc_component * component ,
struct snd_pcm_substream * substream )
2015-03-03 16:21:55 -08:00
{
struct snd_pcm_runtime * runtime = substream - > runtime ;
2020-07-20 10:19:00 +09:00
struct snd_soc_pcm_runtime * soc_runtime = asoc_substream_to_rtd ( substream ) ;
2020-10-08 10:47:01 +05:30
struct snd_soc_dai * cpu_dai = asoc_rtd_to_cpu ( soc_runtime , 0 ) ;
2018-01-29 02:48:52 +00:00
struct lpass_data * drvdata = snd_soc_component_get_drvdata ( component ) ;
2016-10-31 11:25:43 +00:00
struct snd_pcm_runtime * rt = substream - > runtime ;
struct lpass_pcm_data * pcm_data = rt - > private_data ;
2015-05-16 13:32:17 +01:00
struct lpass_variant * v = drvdata - > variant ;
2020-08-14 16:23:01 +05:30
struct lpaif_dmactl * dmactl ;
2020-10-08 10:47:01 +05:30
struct regmap * map ;
2020-08-14 16:23:01 +05:30
int ret , id , ch , dir = substream - > stream ;
2020-10-08 10:47:01 +05:30
unsigned int dai_id = cpu_dai - > driver - > id ;
2016-02-11 12:18:33 +00:00
2016-10-31 11:25:44 +00:00
ch = pcm_data - > dma_ch ;
2020-08-14 16:23:01 +05:30
if ( dir = = SNDRV_PCM_STREAM_PLAYBACK ) {
2020-10-08 10:47:01 +05:30
if ( dai_id = = LPASS_DP_RX ) {
dmactl = drvdata - > hdmi_rd_dmactl ;
map = drvdata - > hdmiif_map ;
} else {
dmactl = drvdata - > rd_dmactl ;
map = drvdata - > lpaif_map ;
}
2020-08-14 16:23:01 +05:30
id = pcm_data - > dma_ch ;
} else {
dmactl = drvdata - > wr_dmactl ;
id = pcm_data - > dma_ch - v - > wrdma_channel_start ;
2020-10-08 10:47:01 +05:30
map = drvdata - > lpaif_map ;
2020-08-14 16:23:01 +05:30
}
2015-03-03 16:21:55 -08:00
2020-10-08 10:47:01 +05:30
ret = regmap_write ( map , LPAIF_DMABASE_REG ( v , ch , dir , dai_id ) ,
runtime - > dma_addr ) ;
2015-03-03 16:21:55 -08:00
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev , " error writing to rdmabase reg: %d \n " ,
ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
2020-10-08 10:47:01 +05:30
ret = regmap_write ( map , LPAIF_DMABUFF_REG ( v , ch , dir , dai_id ) ,
2015-03-03 16:21:55 -08:00
( snd_pcm_lib_buffer_bytes ( substream ) > > 2 ) - 1 ) ;
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev , " error writing to rdmabuff reg: %d \n " ,
ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
2020-10-08 10:47:01 +05:30
ret = regmap_write ( map , LPAIF_DMAPER_REG ( v , ch , dir , dai_id ) ,
2015-03-03 16:21:55 -08:00
( snd_pcm_lib_period_bytes ( substream ) > > 2 ) - 1 ) ;
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev , " error writing to rdmaper reg: %d \n " ,
ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
2020-08-14 16:23:01 +05:30
ret = regmap_fields_write ( dmactl - > enable , id , LPAIF_DMACTL_ENABLE_ON ) ;
2015-03-03 16:21:55 -08:00
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev , " error writing to rdmactl reg: %d \n " ,
ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
return 0 ;
}
2019-10-02 14:33:29 +09:00
static int lpass_platform_pcmops_trigger ( struct snd_soc_component * component ,
struct snd_pcm_substream * substream ,
int cmd )
2015-03-03 16:21:55 -08:00
{
2020-07-20 10:19:00 +09:00
struct snd_soc_pcm_runtime * soc_runtime = asoc_substream_to_rtd ( substream ) ;
2020-10-08 10:47:01 +05:30
struct snd_soc_dai * cpu_dai = asoc_rtd_to_cpu ( soc_runtime , 0 ) ;
2018-01-29 02:48:52 +00:00
struct lpass_data * drvdata = snd_soc_component_get_drvdata ( component ) ;
2016-10-31 11:25:43 +00:00
struct snd_pcm_runtime * rt = substream - > runtime ;
struct lpass_pcm_data * pcm_data = rt - > private_data ;
2015-05-16 13:32:17 +01:00
struct lpass_variant * v = drvdata - > variant ;
2020-08-14 16:23:01 +05:30
struct lpaif_dmactl * dmactl ;
2020-10-08 10:47:01 +05:30
struct regmap * map ;
2020-08-14 16:23:01 +05:30
int ret , ch , id ;
int dir = substream - > stream ;
2020-10-08 10:47:01 +05:30
unsigned int reg_irqclr = 0 , val_irqclr = 0 ;
unsigned int reg_irqen = 0 , val_irqen = 0 , val_mask = 0 ;
unsigned int dai_id = cpu_dai - > driver - > id ;
2016-02-11 12:18:33 +00:00
2016-10-31 11:25:44 +00:00
ch = pcm_data - > dma_ch ;
2020-08-14 16:23:01 +05:30
if ( dir = = SNDRV_PCM_STREAM_PLAYBACK ) {
id = pcm_data - > dma_ch ;
2020-11-23 21:47:53 +05:30
if ( dai_id = = LPASS_DP_RX ) {
2020-10-08 10:47:01 +05:30
dmactl = drvdata - > hdmi_rd_dmactl ;
2020-11-23 21:47:53 +05:30
map = drvdata - > hdmiif_map ;
} else {
2020-10-08 10:47:01 +05:30
dmactl = drvdata - > rd_dmactl ;
2020-11-23 21:47:53 +05:30
map = drvdata - > lpaif_map ;
}
2020-08-14 16:23:01 +05:30
} else {
dmactl = drvdata - > wr_dmactl ;
id = pcm_data - > dma_ch - v - > wrdma_channel_start ;
2020-11-23 21:47:53 +05:30
map = drvdata - > lpaif_map ;
}
2015-03-03 16:21:55 -08:00
switch ( cmd ) {
case SNDRV_PCM_TRIGGER_START :
case SNDRV_PCM_TRIGGER_RESUME :
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
2020-10-08 10:47:01 +05:30
ret = regmap_fields_write ( dmactl - > enable , id ,
LPAIF_DMACTL_ENABLE_ON ) ;
2015-03-03 16:21:55 -08:00
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev ,
2020-10-08 10:47:01 +05:30
" error writing to rdmactl reg: %d \n " , ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
2020-10-08 10:47:01 +05:30
switch ( dai_id ) {
case LPASS_DP_RX :
ret = regmap_fields_write ( dmactl - > dyncclk , id ,
LPAIF_DMACTL_DYNCLK_ON ) ;
if ( ret ) {
dev_err ( soc_runtime - > dev ,
" error writing to rdmactl reg: %d \n " , ret ) ;
return ret ;
}
reg_irqclr = LPASS_HDMITX_APP_IRQCLEAR_REG ( v ) ;
val_irqclr = ( LPAIF_IRQ_ALL ( ch ) |
LPAIF_IRQ_HDMI_REQ_ON_PRELOAD ( ch ) |
LPAIF_IRQ_HDMI_METADONE |
LPAIF_IRQ_HDMI_SDEEP_AUD_DIS ( ch ) ) ;
reg_irqen = LPASS_HDMITX_APP_IRQEN_REG ( v ) ;
val_mask = ( LPAIF_IRQ_ALL ( ch ) |
LPAIF_IRQ_HDMI_REQ_ON_PRELOAD ( ch ) |
LPAIF_IRQ_HDMI_METADONE |
LPAIF_IRQ_HDMI_SDEEP_AUD_DIS ( ch ) ) ;
val_irqen = ( LPAIF_IRQ_ALL ( ch ) |
LPAIF_IRQ_HDMI_REQ_ON_PRELOAD ( ch ) |
LPAIF_IRQ_HDMI_METADONE |
LPAIF_IRQ_HDMI_SDEEP_AUD_DIS ( ch ) ) ;
break ;
case MI2S_PRIMARY :
case MI2S_SECONDARY :
2021-01-19 17:15:27 +00:00
case MI2S_TERTIARY :
case MI2S_QUATERNARY :
case MI2S_QUINARY :
2020-10-08 10:47:01 +05:30
reg_irqclr = LPAIF_IRQCLEAR_REG ( v , LPAIF_IRQ_PORT_HOST ) ;
val_irqclr = LPAIF_IRQ_ALL ( ch ) ;
2015-03-03 16:21:55 -08:00
2020-10-08 10:47:01 +05:30
reg_irqen = LPAIF_IRQEN_REG ( v , LPAIF_IRQ_PORT_HOST ) ;
val_mask = LPAIF_IRQ_ALL ( ch ) ;
val_irqen = LPAIF_IRQ_ALL ( ch ) ;
break ;
default :
dev_err ( soc_runtime - > dev , " %s: invalid %d interface \n " , __func__ , dai_id ) ;
return - EINVAL ;
}
ret = regmap_write ( map , reg_irqclr , val_irqclr ) ;
2015-03-03 16:21:55 -08:00
if ( ret ) {
2020-10-08 10:47:01 +05:30
dev_err ( soc_runtime - > dev , " error writing to irqclear reg: %d \n " , ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
2020-10-08 10:47:01 +05:30
ret = regmap_update_bits ( map , reg_irqen , val_mask , val_irqen ) ;
2015-03-03 16:21:55 -08:00
if ( ret ) {
2020-10-08 10:47:01 +05:30
dev_err ( soc_runtime - > dev , " error writing to irqen reg: %d \n " , ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
break ;
case SNDRV_PCM_TRIGGER_STOP :
case SNDRV_PCM_TRIGGER_SUSPEND :
case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
2020-08-14 16:23:01 +05:30
ret = regmap_fields_write ( dmactl - > enable , id ,
LPAIF_DMACTL_ENABLE_OFF ) ;
2015-03-03 16:21:55 -08:00
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev ,
" error writing to rdmactl reg: %d \n " , ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
2020-10-08 10:47:01 +05:30
switch ( dai_id ) {
case LPASS_DP_RX :
ret = regmap_fields_write ( dmactl - > dyncclk , id ,
LPAIF_DMACTL_DYNCLK_OFF ) ;
if ( ret ) {
dev_err ( soc_runtime - > dev ,
" error writing to rdmactl reg: %d \n " , ret ) ;
return ret ;
}
reg_irqen = LPASS_HDMITX_APP_IRQEN_REG ( v ) ;
val_mask = ( LPAIF_IRQ_ALL ( ch ) |
LPAIF_IRQ_HDMI_REQ_ON_PRELOAD ( ch ) |
LPAIF_IRQ_HDMI_METADONE |
LPAIF_IRQ_HDMI_SDEEP_AUD_DIS ( ch ) ) ;
val_irqen = 0 ;
break ;
case MI2S_PRIMARY :
case MI2S_SECONDARY :
2021-01-19 17:15:27 +00:00
case MI2S_TERTIARY :
case MI2S_QUATERNARY :
case MI2S_QUINARY :
2020-10-08 10:47:01 +05:30
reg_irqen = LPAIF_IRQEN_REG ( v , LPAIF_IRQ_PORT_HOST ) ;
val_mask = LPAIF_IRQ_ALL ( ch ) ;
val_irqen = 0 ;
break ;
default :
dev_err ( soc_runtime - > dev , " %s: invalid %d interface \n " , __func__ , dai_id ) ;
return - EINVAL ;
}
2015-03-03 16:21:55 -08:00
2020-10-08 10:47:01 +05:30
ret = regmap_update_bits ( map , reg_irqen , val_mask , val_irqen ) ;
2015-03-03 16:21:55 -08:00
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev ,
" error writing to irqen reg: %d \n " , ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
break ;
}
return 0 ;
}
static snd_pcm_uframes_t lpass_platform_pcmops_pointer (
2019-10-02 14:33:29 +09:00
struct snd_soc_component * component ,
2015-03-03 16:21:55 -08:00
struct snd_pcm_substream * substream )
{
2020-07-20 10:19:00 +09:00
struct snd_soc_pcm_runtime * soc_runtime = asoc_substream_to_rtd ( substream ) ;
2020-10-08 10:47:01 +05:30
struct snd_soc_dai * cpu_dai = asoc_rtd_to_cpu ( soc_runtime , 0 ) ;
2018-01-29 02:48:52 +00:00
struct lpass_data * drvdata = snd_soc_component_get_drvdata ( component ) ;
2016-10-31 11:25:43 +00:00
struct snd_pcm_runtime * rt = substream - > runtime ;
struct lpass_pcm_data * pcm_data = rt - > private_data ;
2015-05-16 13:32:17 +01:00
struct lpass_variant * v = drvdata - > variant ;
2015-03-03 16:21:55 -08:00
unsigned int base_addr , curr_addr ;
2016-02-11 12:18:33 +00:00
int ret , ch , dir = substream - > stream ;
2020-10-08 10:47:01 +05:30
struct regmap * map ;
unsigned int dai_id = cpu_dai - > driver - > id ;
if ( dai_id = = LPASS_DP_RX )
map = drvdata - > hdmiif_map ;
else
map = drvdata - > lpaif_map ;
2016-02-11 12:18:33 +00:00
2016-10-31 11:25:44 +00:00
ch = pcm_data - > dma_ch ;
2015-03-03 16:21:55 -08:00
2020-10-08 10:47:01 +05:30
ret = regmap_read ( map ,
LPAIF_DMABASE_REG ( v , ch , dir , dai_id ) , & base_addr ) ;
2015-03-03 16:21:55 -08:00
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev ,
" error reading from rdmabase reg: %d \n " , ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
2020-10-08 10:47:01 +05:30
ret = regmap_read ( map ,
LPAIF_DMACURR_REG ( v , ch , dir , dai_id ) , & curr_addr ) ;
2015-03-03 16:21:55 -08:00
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev ,
" error reading from rdmacurr reg: %d \n " , ret ) ;
2015-03-03 16:21:55 -08:00
return ret ;
}
return bytes_to_frames ( substream - > runtime , curr_addr - base_addr ) ;
}
2019-10-02 14:33:29 +09:00
static int lpass_platform_pcmops_mmap ( struct snd_soc_component * component ,
struct snd_pcm_substream * substream ,
struct vm_area_struct * vma )
2015-03-03 16:21:55 -08:00
{
struct snd_pcm_runtime * runtime = substream - > runtime ;
2020-08-14 16:22:59 +05:30
return dma_mmap_coherent ( component - > dev , vma , runtime - > dma_area ,
runtime - > dma_addr , runtime - > dma_bytes ) ;
2015-03-03 16:21:55 -08:00
}
2015-05-21 22:53:14 +01:00
static irqreturn_t lpass_dma_interrupt_handler (
struct snd_pcm_substream * substream ,
struct lpass_data * drvdata ,
int chan , u32 interrupts )
2015-03-03 16:21:55 -08:00
{
2020-07-20 10:19:00 +09:00
struct snd_soc_pcm_runtime * soc_runtime = asoc_substream_to_rtd ( substream ) ;
2020-10-08 10:47:01 +05:30
struct snd_soc_dai * cpu_dai = asoc_rtd_to_cpu ( soc_runtime , 0 ) ;
2015-05-16 13:32:17 +01:00
struct lpass_variant * v = drvdata - > variant ;
2015-03-03 16:21:55 -08:00
irqreturn_t ret = IRQ_NONE ;
2015-05-21 22:53:14 +01:00
int rv ;
2020-10-08 10:47:01 +05:30
unsigned int reg = 0 , val = 0 ;
struct regmap * map ;
unsigned int dai_id = cpu_dai - > driver - > id ;
switch ( dai_id ) {
case LPASS_DP_RX :
map = drvdata - > hdmiif_map ;
reg = LPASS_HDMITX_APP_IRQCLEAR_REG ( v ) ;
val = ( LPAIF_IRQ_HDMI_REQ_ON_PRELOAD ( chan ) |
LPAIF_IRQ_HDMI_METADONE |
LPAIF_IRQ_HDMI_SDEEP_AUD_DIS ( chan ) ) ;
break ;
case MI2S_PRIMARY :
case MI2S_SECONDARY :
2021-01-19 17:15:27 +00:00
case MI2S_TERTIARY :
case MI2S_QUATERNARY :
case MI2S_QUINARY :
2020-10-08 10:47:01 +05:30
map = drvdata - > lpaif_map ;
reg = LPAIF_IRQCLEAR_REG ( v , LPAIF_IRQ_PORT_HOST ) ;
val = 0 ;
break ;
default :
dev_err ( soc_runtime - > dev , " %s: invalid %d interface \n " , __func__ , dai_id ) ;
return - EINVAL ;
}
2015-05-16 13:32:34 +01:00
if ( interrupts & LPAIF_IRQ_PER ( chan ) ) {
2020-10-08 10:47:01 +05:30
rv = regmap_write ( map , reg , LPAIF_IRQ_PER ( chan ) | val ) ;
2015-03-03 16:21:55 -08:00
if ( rv ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev ,
" error writing to irqclear reg: %d \n " , rv ) ;
2015-03-03 16:21:55 -08:00
return IRQ_NONE ;
}
snd_pcm_period_elapsed ( substream ) ;
ret = IRQ_HANDLED ;
}
2015-05-16 13:32:34 +01:00
if ( interrupts & LPAIF_IRQ_XRUN ( chan ) ) {
2020-10-08 10:47:01 +05:30
rv = regmap_write ( map , reg , LPAIF_IRQ_XRUN ( chan ) | val ) ;
2015-03-03 16:21:55 -08:00
if ( rv ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev ,
" error writing to irqclear reg: %d \n " , rv ) ;
2015-03-03 16:21:55 -08:00
return IRQ_NONE ;
}
2017-01-30 13:03:37 -08:00
dev_warn ( soc_runtime - > dev , " xrun warning \n " ) ;
2018-07-04 16:01:44 +02:00
snd_pcm_stop_xrun ( substream ) ;
2015-03-03 16:21:55 -08:00
ret = IRQ_HANDLED ;
}
2015-05-16 13:32:34 +01:00
if ( interrupts & LPAIF_IRQ_ERR ( chan ) ) {
2020-10-08 10:47:01 +05:30
rv = regmap_write ( map , reg , LPAIF_IRQ_ERR ( chan ) | val ) ;
2015-03-03 16:21:55 -08:00
if ( rv ) {
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev ,
" error writing to irqclear reg: %d \n " , rv ) ;
2015-03-03 16:21:55 -08:00
return IRQ_NONE ;
}
2017-01-30 13:03:37 -08:00
dev_err ( soc_runtime - > dev , " bus access error \n " ) ;
2015-03-03 16:21:55 -08:00
snd_pcm_stop ( substream , SNDRV_PCM_STATE_DISCONNECTED ) ;
ret = IRQ_HANDLED ;
}
2020-10-08 10:47:01 +05:30
if ( interrupts & val ) {
rv = regmap_write ( map , reg , val ) ;
if ( rv ) {
dev_err ( soc_runtime - > dev ,
" error writing to irqclear reg: %d \n " , rv ) ;
return IRQ_NONE ;
}
ret = IRQ_HANDLED ;
}
2015-03-03 16:21:55 -08:00
return ret ;
}
2015-05-21 22:53:14 +01:00
static irqreturn_t lpass_platform_lpaif_irq ( int irq , void * data )
{
struct lpass_data * drvdata = data ;
struct lpass_variant * v = drvdata - > variant ;
unsigned int irqs ;
int rv , chan ;
rv = regmap_read ( drvdata - > lpaif_map ,
LPAIF_IRQSTAT_REG ( v , LPAIF_IRQ_PORT_HOST ) , & irqs ) ;
if ( rv ) {
2017-01-30 13:03:37 -08:00
pr_err ( " error reading from irqstat reg: %d \n " , rv ) ;
2015-05-21 22:53:14 +01:00
return IRQ_NONE ;
}
/* Handle per channel interrupts */
for ( chan = 0 ; chan < LPASS_MAX_DMA_CHANNELS ; chan + + ) {
if ( irqs & LPAIF_IRQ_ALL ( chan ) & & drvdata - > substream [ chan ] ) {
rv = lpass_dma_interrupt_handler (
drvdata - > substream [ chan ] ,
drvdata , chan , irqs ) ;
if ( rv ! = IRQ_HANDLED )
return rv ;
}
}
return IRQ_HANDLED ;
}
2020-10-08 10:47:01 +05:30
static irqreturn_t lpass_platform_hdmiif_irq ( int irq , void * data )
{
struct lpass_data * drvdata = data ;
struct lpass_variant * v = drvdata - > variant ;
unsigned int irqs ;
int rv , chan ;
rv = regmap_read ( drvdata - > hdmiif_map ,
LPASS_HDMITX_APP_IRQSTAT_REG ( v ) , & irqs ) ;
if ( rv ) {
pr_err ( " error reading from irqstat reg: %d \n " , rv ) ;
return IRQ_NONE ;
}
/* Handle per channel interrupts */
for ( chan = 0 ; chan < LPASS_MAX_HDMI_DMA_CHANNELS ; chan + + ) {
if ( irqs & ( LPAIF_IRQ_ALL ( chan ) | LPAIF_IRQ_HDMI_REQ_ON_PRELOAD ( chan ) |
LPAIF_IRQ_HDMI_METADONE |
LPAIF_IRQ_HDMI_SDEEP_AUD_DIS ( chan ) )
& & drvdata - > hdmi_substream [ chan ] ) {
rv = lpass_dma_interrupt_handler (
drvdata - > hdmi_substream [ chan ] ,
drvdata , chan , irqs ) ;
if ( rv ! = IRQ_HANDLED )
return rv ;
}
}
return IRQ_HANDLED ;
}
2019-10-02 14:33:29 +09:00
static int lpass_platform_pcm_new ( struct snd_soc_component * component ,
struct snd_soc_pcm_runtime * soc_runtime )
2015-03-03 16:21:55 -08:00
{
struct snd_pcm * pcm = soc_runtime - > pcm ;
2016-02-11 12:18:33 +00:00
struct snd_pcm_substream * psubstream , * csubstream ;
2021-02-18 16:29:08 -06:00
int ret ;
2016-02-11 12:17:17 +00:00
size_t size = lpass_platform_pcm_hardware . buffer_bytes_max ;
2015-05-16 13:32:34 +01:00
2016-02-11 12:18:33 +00:00
psubstream = pcm - > streams [ SNDRV_PCM_STREAM_PLAYBACK ] . substream ;
if ( psubstream ) {
ret = snd_dma_alloc_pages ( SNDRV_DMA_TYPE_DEV ,
2018-01-29 02:48:52 +00:00
component - > dev ,
2016-02-11 12:18:33 +00:00
size , & psubstream - > dma_buffer ) ;
if ( ret ) {
2016-10-31 11:25:43 +00:00
dev_err ( soc_runtime - > dev , " Cannot allocate buffer(s) \n " ) ;
return ret ;
2016-02-11 12:18:33 +00:00
}
}
csubstream = pcm - > streams [ SNDRV_PCM_STREAM_CAPTURE ] . substream ;
if ( csubstream ) {
ret = snd_dma_alloc_pages ( SNDRV_DMA_TYPE_DEV ,
2018-01-29 02:48:52 +00:00
component - > dev ,
2016-02-11 12:18:33 +00:00
size , & csubstream - > dma_buffer ) ;
if ( ret ) {
2016-10-31 11:25:43 +00:00
dev_err ( soc_runtime - > dev , " Cannot allocate buffer(s) \n " ) ;
if ( psubstream )
snd_dma_free_pages ( & psubstream - > dma_buffer ) ;
return ret ;
2016-02-11 12:18:33 +00:00
}
2016-10-31 11:25:43 +00:00
2015-03-03 16:21:55 -08:00
}
return 0 ;
}
2019-10-02 14:33:29 +09:00
static void lpass_platform_pcm_free ( struct snd_soc_component * component ,
struct snd_pcm * pcm )
2015-03-03 16:21:55 -08:00
{
2016-02-11 12:18:33 +00:00
struct snd_pcm_substream * substream ;
2016-10-31 11:25:43 +00:00
int i ;
2016-02-11 12:18:33 +00:00
2020-02-17 17:28:44 +09:00
for_each_pcm_streams ( i ) {
2016-02-11 12:18:33 +00:00
substream = pcm - > streams [ i ] . substream ;
if ( substream ) {
snd_dma_free_pages ( & substream - > dma_buffer ) ;
substream - > dma_buffer . area = NULL ;
substream - > dma_buffer . addr = 0 ;
}
}
2015-03-03 16:21:55 -08:00
}
2020-12-17 13:38:34 +05:30
static int lpass_platform_pcmops_suspend ( struct snd_soc_component * component )
{
struct lpass_data * drvdata = snd_soc_component_get_drvdata ( component ) ;
struct regmap * map ;
unsigned int dai_id = component - > id ;
if ( dai_id = = LPASS_DP_RX )
map = drvdata - > hdmiif_map ;
else
map = drvdata - > lpaif_map ;
regcache_cache_only ( map , true ) ;
regcache_mark_dirty ( map ) ;
return 0 ;
}
static int lpass_platform_pcmops_resume ( struct snd_soc_component * component )
{
struct lpass_data * drvdata = snd_soc_component_get_drvdata ( component ) ;
struct regmap * map ;
unsigned int dai_id = component - > id ;
if ( dai_id = = LPASS_DP_RX )
map = drvdata - > hdmiif_map ;
else
map = drvdata - > lpaif_map ;
regcache_cache_only ( map , false ) ;
return regcache_sync ( map ) ;
}
2018-01-29 02:48:52 +00:00
static const struct snd_soc_component_driver lpass_component_driver = {
. name = DRV_NAME ,
2019-10-02 14:33:29 +09:00
. open = lpass_platform_pcmops_open ,
. close = lpass_platform_pcmops_close ,
. hw_params = lpass_platform_pcmops_hw_params ,
. hw_free = lpass_platform_pcmops_hw_free ,
. prepare = lpass_platform_pcmops_prepare ,
. trigger = lpass_platform_pcmops_trigger ,
. pointer = lpass_platform_pcmops_pointer ,
. mmap = lpass_platform_pcmops_mmap ,
. pcm_construct = lpass_platform_pcm_new ,
. pcm_destruct = lpass_platform_pcm_free ,
2020-12-17 13:38:34 +05:30
. suspend = lpass_platform_pcmops_suspend ,
. resume = lpass_platform_pcmops_resume ,
2019-10-02 14:33:29 +09:00
2015-03-03 16:21:55 -08:00
} ;
int asoc_qcom_lpass_platform_register ( struct platform_device * pdev )
{
struct lpass_data * drvdata = platform_get_drvdata ( pdev ) ;
2015-05-21 22:53:14 +01:00
struct lpass_variant * v = drvdata - > variant ;
int ret ;
2015-03-03 16:21:55 -08:00
2020-10-08 10:46:59 +05:30
drvdata - > lpaif_irq = platform_get_irq_byname ( pdev , " lpass-irq-lpaif " ) ;
2019-07-30 11:15:49 -07:00
if ( drvdata - > lpaif_irq < 0 )
2015-03-03 16:21:55 -08:00
return - ENODEV ;
2015-05-21 22:53:14 +01:00
/* ensure audio hardware is disabled */
ret = regmap_write ( drvdata - > lpaif_map ,
LPAIF_IRQEN_REG ( v , LPAIF_IRQ_PORT_HOST ) , 0 ) ;
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( & pdev - > dev , " error writing to irqen reg: %d \n " , ret ) ;
2015-05-21 22:53:14 +01:00
return ret ;
}
ret = devm_request_irq ( & pdev - > dev , drvdata - > lpaif_irq ,
lpass_platform_lpaif_irq , IRQF_TRIGGER_RISING ,
" lpass-irq-lpaif " , drvdata ) ;
if ( ret ) {
2017-01-30 13:03:37 -08:00
dev_err ( & pdev - > dev , " irq request failed: %d \n " , ret ) ;
2015-05-21 22:53:14 +01:00
return ret ;
}
2020-08-14 16:23:01 +05:30
ret = lpass_platform_alloc_dmactl_fields ( & pdev - > dev ,
drvdata - > lpaif_map ) ;
if ( ret ) {
dev_err ( & pdev - > dev ,
" error initializing dmactl fields: %d \n " , ret ) ;
return ret ;
}
2015-05-21 22:53:14 +01:00
2020-10-08 10:47:01 +05:30
if ( drvdata - > hdmi_port_enable ) {
drvdata - > hdmiif_irq = platform_get_irq_byname ( pdev , " lpass-irq-hdmi " ) ;
if ( drvdata - > hdmiif_irq < 0 )
return - ENODEV ;
ret = devm_request_irq ( & pdev - > dev , drvdata - > hdmiif_irq ,
lpass_platform_hdmiif_irq , 0 , " lpass-irq-hdmi " , drvdata ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " irq hdmi request failed: %d \n " , ret ) ;
return ret ;
}
ret = regmap_write ( drvdata - > hdmiif_map ,
LPASS_HDMITX_APP_IRQEN_REG ( v ) , 0 ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " error writing to hdmi irqen reg: %d \n " , ret ) ;
return ret ;
}
ret = lpass_platform_alloc_hdmidmactl_fields ( & pdev - > dev ,
drvdata - > hdmiif_map ) ;
if ( ret ) {
dev_err ( & pdev - > dev ,
" error initializing hdmidmactl fields: %d \n " , ret ) ;
return ret ;
}
}
2018-01-29 02:48:52 +00:00
return devm_snd_soc_register_component ( & pdev - > dev ,
& lpass_component_driver , NULL , 0 ) ;
2015-03-03 16:21:55 -08:00
}
EXPORT_SYMBOL_GPL ( asoc_qcom_lpass_platform_register ) ;
MODULE_DESCRIPTION ( " QTi LPASS Platform Driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;