135 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* SPDX-License-Identifier: GPL-2.0-or-later */
 | |
| /*
 | |
|  * Rockchip DLP (Digital Loopback) driver
 | |
|  *
 | |
|  * Copyright (C) 2022 Rockchip Electronics Co., Ltd.
 | |
|  * Author: Sugar Zhang <sugar.zhang@rock-chips.com>
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #ifndef _ROCKCHIP_DLP_H
 | |
| #define _ROCKCHIP_DLP_H
 | |
| 
 | |
| #include "rockchip_dlp_pcm.h"
 | |
| 
 | |
| #define DLP_MAX_DRDS	8
 | |
| 
 | |
| /* MUST: enum dlp_mode should be match to dlp_text */
 | |
| enum dlp_mode {
 | |
| 	DLP_MODE_DISABLED,
 | |
| 	DLP_MODE_2CH_1LP_1MIC,		/* replace cap-ch-0   with play-ch-0 */
 | |
| 	DLP_MODE_2CH_1MIC_1LP,		/* replace cap-ch-1   with play-ch-1 */
 | |
| 	DLP_MODE_2CH_1MIC_1LP_MIX,	/* replace cap-ch-1   with play-ch-all-mix */
 | |
| 	DLP_MODE_2CH_2LP,		/* replace cap-ch-0~1 with play-ch-0~1 */
 | |
| 	DLP_MODE_4CH_2MIC_2LP,		/* replace cap-ch-2~3 with play-ch-0~1 */
 | |
| 	DLP_MODE_4CH_2MIC_1LP_MIX,	/* replace cap-ch-3   with play-ch-all-mix */
 | |
| 	DLP_MODE_4CH_4LP,		/* replace cap-ch-0~3 with play-ch-0~3 */
 | |
| 	DLP_MODE_6CH_4MIC_2LP,		/* replace cap-ch-4~5 with play-ch-0~1 */
 | |
| 	DLP_MODE_6CH_4MIC_1LP_MIX,	/* replace cap-ch-4   with play-ch-all-mix */
 | |
| 	DLP_MODE_6CH_6LP,		/* replace cap-ch-0~5 with play-ch-0~5 */
 | |
| 	DLP_MODE_8CH_6MIC_2LP,		/* replace cap-ch-6~7 with play-ch-0~1 */
 | |
| 	DLP_MODE_8CH_6MIC_1LP_MIX,	/* replace cap-ch-6   with play-ch-all-mix */
 | |
| 	DLP_MODE_8CH_8LP,		/* replace cap-ch-0~7 with play-ch-0~7 */
 | |
| 	DLP_MODE_10CH_8MIC_2LP,		/* replace cap-ch-8~9 with play-ch-0~1 */
 | |
| 	DLP_MODE_10CH_8MIC_1LP_MIX,	/* replace cap-ch-8   with play-ch-all-mix */
 | |
| 	DLP_MODE_16CH_8MIC_8LP,		/* replace cap-ch-8~f with play-ch-8~f */
 | |
| };
 | |
| 
 | |
| struct dlp;
 | |
| 
 | |
| struct dlp_runtime_data {
 | |
| 	struct dlp *parent;
 | |
| 	struct kref refcount;
 | |
| 	struct list_head node;
 | |
| 	char *buf;
 | |
| 	snd_pcm_uframes_t buf_sz;
 | |
| 	snd_pcm_uframes_t last_buf_sz;
 | |
| 	snd_pcm_uframes_t period_sz;
 | |
| 	int64_t hw_ptr;
 | |
| 	int64_t hw_ptr_delta; /* play-ptr - cap-ptr */
 | |
| 	atomic64_t period_elapsed;
 | |
| 	atomic_t stop;
 | |
| 	unsigned int frame_bytes;
 | |
| 	unsigned int channels;
 | |
| 	unsigned int buf_ofs;
 | |
| 	int stream;
 | |
| };
 | |
| 
 | |
| struct dlp {
 | |
| 	struct device *dev;
 | |
| 	struct list_head drd_avl_list;
 | |
| 	struct list_head drd_rdy_list;
 | |
| 	struct list_head drd_ref_list;
 | |
| 	struct dlp_runtime_data drds[DLP_MAX_DRDS];
 | |
| 	struct dlp_runtime_data *drd_pb_shadow;
 | |
| 	struct snd_soc_component component;
 | |
| 	const struct snd_dlp_config *config;
 | |
| 	enum dlp_mode mode;
 | |
| 	int drd_avl_count;
 | |
| 	atomic_t active;
 | |
| 	spinlock_t lock;
 | |
| };
 | |
| 
 | |
| typedef snd_pcm_uframes_t (*dma_pointer_f)(struct snd_soc_component *component,
 | |
| 					   struct snd_pcm_substream *substream);
 | |
| 
 | |
| static inline struct dlp *soc_component_to_dlp(struct snd_soc_component *p)
 | |
| {
 | |
| 	return container_of(p, struct dlp, component);
 | |
| }
 | |
| 
 | |
| static inline struct dlp_runtime_data *substream_to_drd(
 | |
| 	const struct snd_pcm_substream *substream)
 | |
| {
 | |
| 	if (!substream || !substream->runtime)
 | |
| 		return NULL;
 | |
| 
 | |
| 	return substream->runtime->private_data;
 | |
| }
 | |
| 
 | |
| static inline ssize_t dlp_channels_to_bytes(struct dlp_runtime_data *drd,
 | |
| 					    int channels)
 | |
| {
 | |
| 	return (drd->frame_bytes / drd->channels) * channels;
 | |
| }
 | |
| 
 | |
| static inline ssize_t dlp_frames_to_bytes(struct dlp_runtime_data *drd,
 | |
| 					  snd_pcm_sframes_t size)
 | |
| {
 | |
| 	return size * drd->frame_bytes;
 | |
| }
 | |
| 
 | |
| static inline snd_pcm_sframes_t dlp_bytes_to_frames(struct dlp_runtime_data *drd,
 | |
| 						    ssize_t size)
 | |
| {
 | |
| 	return size / drd->frame_bytes;
 | |
| }
 | |
| 
 | |
| void dlp_dma_complete(struct dlp *dlp, struct dlp_runtime_data *drd);
 | |
| int dlp_open(struct dlp *dlp, struct dlp_runtime_data *drd,
 | |
| 	     struct snd_pcm_substream *substream);
 | |
| int dlp_close(struct dlp *dlp, struct dlp_runtime_data *drd,
 | |
| 	      struct snd_pcm_substream *substream);
 | |
| int dlp_hw_params(struct snd_soc_component *component,
 | |
| 		  struct snd_pcm_substream *substream,
 | |
| 		  struct snd_pcm_hw_params *params);
 | |
| int dlp_start(struct snd_soc_component *component,
 | |
| 	      struct snd_pcm_substream *substream,
 | |
| 	      struct device *dev,
 | |
| 	      dma_pointer_f dma_pointer);
 | |
| void dlp_stop(struct snd_soc_component *component,
 | |
| 	      struct snd_pcm_substream *substream,
 | |
| 	      dma_pointer_f dma_pointer);
 | |
| int dlp_copy_user(struct snd_soc_component *component,
 | |
| 		  struct snd_pcm_substream *substream,
 | |
| 		  int channel, unsigned long hwoff,
 | |
| 		  void __user *buf, unsigned long bytes);
 | |
| int dlp_prepare(struct snd_soc_component *component,
 | |
| 		struct snd_pcm_substream *substream);
 | |
| int dlp_probe(struct snd_soc_component *component);
 | |
| int dlp_register(struct dlp *dlp, struct device *dev,
 | |
| 		 const struct snd_soc_component_driver *driver,
 | |
| 		 const struct snd_dlp_config *config);
 | |
| 
 | |
| #endif
 |