2020-05-01 09:58:50 -05:00
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2019-04-12 11:08:46 -05:00
//
// This file is provided under a dual BSD/GPLv2 license. When using or
// redistributing this file, you may do so under either license.
//
// Copyright(c) 2019 Intel Corporation. All rights reserved.
//
// Authors: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
2021-10-04 18:21:45 +03:00
/* Generic SOF IPC code */
2019-04-12 11:08:46 -05:00
# include <linux/device.h>
# include <linux/export.h>
# include <linux/module.h>
# include <linux/types.h>
# include <sound/pcm.h>
# include <sound/sof/stream.h>
2021-10-04 18:21:45 +03:00
# include "ops.h"
# include "sof-priv.h"
2023-01-17 14:25:30 +02:00
# include "sof-audio.h"
2019-04-12 11:08:46 -05:00
2021-10-04 18:21:45 +03:00
struct sof_stream {
2019-04-12 11:08:46 -05:00
size_t posn_offset ;
} ;
2021-10-04 18:21:45 +03:00
/* Mailbox-based Generic IPC implementation */
int sof_ipc_msg_data ( struct snd_sof_dev * sdev ,
2023-01-17 14:25:30 +02:00
struct snd_sof_pcm_stream * sps ,
2021-10-04 18:21:45 +03:00
void * p , size_t sz )
2019-04-12 11:08:46 -05:00
{
2023-01-17 14:25:30 +02:00
if ( ! sps | | ! sdev - > stream_box . size ) {
2021-10-04 18:21:45 +03:00
snd_sof_dsp_mailbox_read ( sdev , sdev - > dsp_box . offset , p , sz ) ;
2019-04-12 11:08:46 -05:00
} else {
2023-01-17 14:25:32 +02:00
size_t posn_offset ;
2019-04-12 11:08:46 -05:00
2023-01-17 14:25:32 +02:00
if ( sps - > substream ) {
struct sof_stream * stream = sps - > substream - > runtime - > private_data ;
2021-09-28 13:35:16 +03:00
2023-01-17 14:25:32 +02:00
/* The stream might already be closed */
if ( ! stream )
return - ESTRPIPE ;
posn_offset = stream - > posn_offset ;
} else {
struct sof_compr_stream * sstream = sps - > cstream - > runtime - > private_data ;
if ( ! sstream )
return - ESTRPIPE ;
posn_offset = sstream - > posn_offset ;
}
snd_sof_dsp_mailbox_read ( sdev , posn_offset , p , sz ) ;
2019-04-12 11:08:46 -05:00
}
2021-09-28 13:35:16 +03:00
return 0 ;
2019-04-12 11:08:46 -05:00
}
2021-10-04 18:21:45 +03:00
EXPORT_SYMBOL ( sof_ipc_msg_data ) ;
2019-04-12 11:08:46 -05:00
2022-03-09 20:27:16 -08:00
int sof_set_stream_data_offset ( struct snd_sof_dev * sdev ,
2023-01-17 14:25:31 +02:00
struct snd_sof_pcm_stream * sps ,
2022-03-09 20:27:16 -08:00
size_t posn_offset )
2019-04-12 11:08:46 -05:00
{
/* check if offset is overflow or it is not aligned */
if ( posn_offset > sdev - > stream_box . size | |
posn_offset % sizeof ( struct sof_ipc_stream_posn ) ! = 0 )
return - EINVAL ;
2023-01-17 14:25:32 +02:00
posn_offset + = sdev - > stream_box . offset ;
if ( sps - > substream ) {
struct sof_stream * stream = sps - > substream - > runtime - > private_data ;
stream - > posn_offset = posn_offset ;
dev_dbg ( sdev - > dev , " pcm: stream dir %d, posn mailbox offset is %zu " ,
sps - > substream - > stream , posn_offset ) ;
} else if ( sps - > cstream ) {
struct sof_compr_stream * sstream = sps - > cstream - > runtime - > private_data ;
2019-04-12 11:08:46 -05:00
2023-01-17 14:25:32 +02:00
sstream - > posn_offset = posn_offset ;
dev_dbg ( sdev - > dev , " compr: stream dir %d, posn mailbox offset is %zu " ,
sps - > cstream - > direction , posn_offset ) ;
} else {
dev_err ( sdev - > dev , " No stream opened " ) ;
return - EINVAL ;
}
2019-04-12 11:08:46 -05:00
return 0 ;
}
2022-03-09 20:27:16 -08:00
EXPORT_SYMBOL ( sof_set_stream_data_offset ) ;
2021-10-04 18:21:45 +03:00
int sof_stream_pcm_open ( struct snd_sof_dev * sdev ,
struct snd_pcm_substream * substream )
2019-04-12 11:08:46 -05:00
{
2021-10-04 18:21:45 +03:00
struct sof_stream * stream = kmalloc ( sizeof ( * stream ) , GFP_KERNEL ) ;
2019-04-12 11:08:46 -05:00
if ( ! stream )
return - ENOMEM ;
/* binding pcm substream to hda stream */
substream - > runtime - > private_data = stream ;
2020-11-18 16:05:45 +02:00
/* align to DMA minimum transfer size */
snd_pcm_hw_constraint_step ( substream - > runtime , 0 , SNDRV_PCM_HW_PARAM_PERIOD_BYTES , 4 ) ;
/* avoid circular buffer wrap in middle of period */
snd_pcm_hw_constraint_integer ( substream - > runtime ,
SNDRV_PCM_HW_PARAM_PERIODS ) ;
2019-04-12 11:08:46 -05:00
return 0 ;
}
2021-10-04 18:21:45 +03:00
EXPORT_SYMBOL ( sof_stream_pcm_open ) ;
2019-04-12 11:08:46 -05:00
2021-10-04 18:21:45 +03:00
int sof_stream_pcm_close ( struct snd_sof_dev * sdev ,
struct snd_pcm_substream * substream )
2019-04-12 11:08:46 -05:00
{
2021-10-04 18:21:45 +03:00
struct sof_stream * stream = substream - > runtime - > private_data ;
2019-04-12 11:08:46 -05:00
substream - > runtime - > private_data = NULL ;
kfree ( stream ) ;
return 0 ;
}
2021-10-04 18:21:45 +03:00
EXPORT_SYMBOL ( sof_stream_pcm_close ) ;
2019-04-12 11:08:46 -05:00
MODULE_LICENSE ( " Dual BSD/GPL " ) ;