2022-05-11 19:23:51 +03:00
// SPDX-License-Identifier: GPL-2.0
//
// Copyright(c) 2021-2022 Intel Corporation. All rights reserved.
//
// Author: Cezary Rojewski <cezary.rojewski@intel.com>
//
# include <sound/soc.h>
# include <sound/hda_codec.h>
# include "hda.h"
static int hda_codec_dai_startup ( struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
{
struct hda_pcm_stream * stream_info ;
struct hda_codec * codec ;
struct hda_pcm * pcm ;
int ret ;
codec = dev_to_hda_codec ( dai - > dev ) ;
stream_info = snd_soc_dai_get_dma_data ( dai , substream ) ;
pcm = container_of ( stream_info , struct hda_pcm , stream [ substream - > stream ] ) ;
dev_dbg ( dai - > dev , " open stream codec: %08x, info: %p, pcm: %p %s substream: %p \n " ,
codec - > core . vendor_id , stream_info , pcm , pcm - > name , substream ) ;
snd_hda_codec_pcm_get ( pcm ) ;
ret = stream_info - > ops . open ( stream_info , codec , substream ) ;
if ( ret < 0 ) {
dev_err ( dai - > dev , " codec open failed: %d \n " , ret ) ;
snd_hda_codec_pcm_put ( pcm ) ;
return ret ;
}
return 0 ;
}
static void hda_codec_dai_shutdown ( struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
{
struct hda_pcm_stream * stream_info ;
struct hda_codec * codec ;
struct hda_pcm * pcm ;
int ret ;
codec = dev_to_hda_codec ( dai - > dev ) ;
stream_info = snd_soc_dai_get_dma_data ( dai , substream ) ;
pcm = container_of ( stream_info , struct hda_pcm , stream [ substream - > stream ] ) ;
dev_dbg ( dai - > dev , " close stream codec: %08x, info: %p, pcm: %p %s substream: %p \n " ,
codec - > core . vendor_id , stream_info , pcm , pcm - > name , substream ) ;
ret = stream_info - > ops . close ( stream_info , codec , substream ) ;
if ( ret < 0 )
dev_err ( dai - > dev , " codec close failed: %d \n " , ret ) ;
snd_hda_codec_pcm_put ( pcm ) ;
}
static int hda_codec_dai_hw_free ( struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
{
struct hda_pcm_stream * stream_info ;
struct hda_codec * codec ;
codec = dev_to_hda_codec ( dai - > dev ) ;
stream_info = snd_soc_dai_get_dma_data ( dai , substream ) ;
snd_hda_codec_cleanup ( codec , stream_info , substream ) ;
return 0 ;
}
static int hda_codec_dai_prepare ( struct snd_pcm_substream * substream , struct snd_soc_dai * dai )
{
struct snd_pcm_runtime * runtime = substream - > runtime ;
struct hda_pcm_stream * stream_info ;
struct hdac_stream * stream ;
struct hda_codec * codec ;
unsigned int format ;
2023-11-17 15:06:02 +03:00
unsigned int bits ;
2022-05-11 19:23:51 +03:00
int ret ;
codec = dev_to_hda_codec ( dai - > dev ) ;
stream = substream - > runtime - > private_data ;
stream_info = snd_soc_dai_get_dma_data ( dai , substream ) ;
2023-11-17 15:06:02 +03:00
bits = snd_hdac_stream_format_bits ( runtime - > format , runtime - > subformat ,
stream_info - > maxbps ) ;
format = snd_hdac_stream_format ( runtime - > channels , bits , runtime - > rate ) ;
2022-05-11 19:23:51 +03:00
ret = snd_hda_codec_prepare ( codec , stream_info , stream - > stream_tag , format , substream ) ;
if ( ret < 0 ) {
dev_err ( dai - > dev , " codec prepare failed: %d \n " , ret ) ;
return ret ;
}
return 0 ;
}
const struct snd_soc_dai_ops snd_soc_hda_codec_dai_ops = {
. startup = hda_codec_dai_startup ,
. shutdown = hda_codec_dai_shutdown ,
. hw_free = hda_codec_dai_hw_free ,
. prepare = hda_codec_dai_prepare ,
} ;
EXPORT_SYMBOL_GPL ( snd_soc_hda_codec_dai_ops ) ;