rsnd.h 7.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Renesas R-Car
 *
 * Copyright (C) 2013 Renesas Solutions Corp.
 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#ifndef RSND_H
#define RSND_H

#include <linux/clk.h>
#include <linux/device.h>
16
#include <linux/dma-mapping.h>
17 18 19
#include <linux/io.h>
#include <linux/list.h>
#include <linux/module.h>
20 21
#include <linux/sh_dma.h>
#include <linux/workqueue.h>
22 23 24 25 26 27 28 29 30 31 32
#include <sound/rcar_snd.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>

/*
 *	pseudo register
 *
 * The register address offsets SRU/SCU/SSIU on Gen1/Gen2 are very different.
 * This driver uses pseudo register in order to hide it.
 * see gen1/gen2 for detail
 */
33
enum rsnd_reg {
34
	/* SRU/SCU */
35 36 37 38 39
	RSND_REG_SRC_ROUTE_SEL,
	RSND_REG_SRC_TMG_SEL0,
	RSND_REG_SRC_TMG_SEL1,
	RSND_REG_SRC_TMG_SEL2,
	RSND_REG_SRC_CTRL,
40 41
	RSND_REG_SSI_MODE0,
	RSND_REG_SSI_MODE1,
42 43
	RSND_REG_BUSIF_MODE,
	RSND_REG_BUSIF_ADINR,
44

45 46 47 48 49 50 51 52 53 54 55
	/* ADG */
	RSND_REG_BRRA,
	RSND_REG_BRRB,
	RSND_REG_SSICKR,
	RSND_REG_AUDIO_CLK_SEL0,
	RSND_REG_AUDIO_CLK_SEL1,
	RSND_REG_AUDIO_CLK_SEL2,
	RSND_REG_AUDIO_CLK_SEL3,
	RSND_REG_AUDIO_CLK_SEL4,
	RSND_REG_AUDIO_CLK_SEL5,

56 57 58 59 60 61 62
	/* SSI */
	RSND_REG_SSICR,
	RSND_REG_SSISR,
	RSND_REG_SSITDR,
	RSND_REG_SSIRDR,
	RSND_REG_SSIWSR,

63 64 65
	RSND_REG_MAX,
};

66
struct rsnd_priv;
67
struct rsnd_mod;
68 69 70
struct rsnd_dai;
struct rsnd_dai_stream;

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
/*
 *	R-Car basic functions
 */
#define rsnd_mod_read(m, r) \
	rsnd_read(rsnd_mod_to_priv(m), m, RSND_REG_##r)
#define rsnd_mod_write(m, r, d) \
	rsnd_write(rsnd_mod_to_priv(m), m, RSND_REG_##r, d)
#define rsnd_mod_bset(m, r, s, d) \
	rsnd_bset(rsnd_mod_to_priv(m), m, RSND_REG_##r, s, d)

u32 rsnd_read(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg);
void rsnd_write(struct rsnd_priv *priv, struct rsnd_mod *mod,
		enum rsnd_reg reg, u32 data);
void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
		    u32 mask, u32 data);

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
/*
 *	R-Car DMA
 */
struct rsnd_dma {
	struct rsnd_priv	*priv;
	struct sh_dmae_slave	slave;
	struct work_struct	work;
	struct dma_chan		*chan;
	enum dma_data_direction dir;
	int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len);
	int (*complete)(struct rsnd_dma *dma);

	int submit_loop;
};

void rsnd_dma_start(struct rsnd_dma *dma);
void rsnd_dma_stop(struct rsnd_dma *dma);
int rsnd_dma_available(struct rsnd_dma *dma);
int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
	int is_play, int id,
	int (*inquiry)(struct rsnd_dma *dma, dma_addr_t *buf, int *len),
	int (*complete)(struct rsnd_dma *dma));
void  rsnd_dma_quit(struct rsnd_priv *priv,
		    struct rsnd_dma *dma);


113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
/*
 *	R-Car sound mod
 */

struct rsnd_mod_ops {
	char *name;
	int (*init)(struct rsnd_mod *mod,
		    struct rsnd_dai *rdai,
		    struct rsnd_dai_stream *io);
	int (*quit)(struct rsnd_mod *mod,
		    struct rsnd_dai *rdai,
		    struct rsnd_dai_stream *io);
	int (*start)(struct rsnd_mod *mod,
		     struct rsnd_dai *rdai,
		     struct rsnd_dai_stream *io);
	int (*stop)(struct rsnd_mod *mod,
		    struct rsnd_dai *rdai,
		    struct rsnd_dai_stream *io);
};

struct rsnd_mod {
	int id;
	struct rsnd_priv *priv;
	struct rsnd_mod_ops *ops;
	struct list_head list; /* connect to rsnd_dai playback/capture */
138
	struct rsnd_dma dma;
139 140 141
};

#define rsnd_mod_to_priv(mod) ((mod)->priv)
142 143
#define rsnd_mod_to_dma(mod) (&(mod)->dma)
#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
144 145 146 147 148 149 150 151 152 153 154 155 156 157
#define rsnd_mod_id(mod) ((mod)->id)
#define for_each_rsnd_mod(pos, n, io)	\
	list_for_each_entry_safe(pos, n, &(io)->head, list)
#define rsnd_mod_call(mod, func, rdai, io)	\
	(!(mod) ? -ENODEV :			\
	 !((mod)->ops->func) ? 0 :		\
	 (mod)->ops->func(mod, rdai, io))

void rsnd_mod_init(struct rsnd_priv *priv,
		   struct rsnd_mod *mod,
		   struct rsnd_mod_ops *ops,
		   int id);
char *rsnd_mod_name(struct rsnd_mod *mod);

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
/*
 *	R-Car sound DAI
 */
#define RSND_DAI_NAME_SIZE	16
struct rsnd_dai_stream {
	struct list_head head; /* head of rsnd_mod list */
	struct snd_pcm_substream *substream;
	int byte_pos;
	int period_pos;
	int byte_per_period;
	int next_period_byte;
};

struct rsnd_dai {
	char name[RSND_DAI_NAME_SIZE];
	struct rsnd_dai_platform_info *info; /* rcar_snd.h */
	struct rsnd_dai_stream playback;
	struct rsnd_dai_stream capture;

	int clk_master:1;
	int bit_clk_inv:1;
	int frm_clk_inv:1;
	int sys_delay:1;
	int data_alignment:1;
};

#define rsnd_dai_nr(priv) ((priv)->dai_nr)
#define for_each_rsnd_dai(rdai, priv, i)		\
	for (i = 0, (rdai) = rsnd_dai_get(priv, i);	\
	     i < rsnd_dai_nr(priv);			\
	     i++, (rdai) = rsnd_dai_get(priv, i))

struct rsnd_dai *rsnd_dai_get(struct rsnd_priv *priv, int id);
191 192 193
int rsnd_dai_disconnect(struct rsnd_mod *mod);
int rsnd_dai_connect(struct rsnd_dai *rdai, struct rsnd_mod *mod,
		     struct rsnd_dai_stream *io);
194
int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io);
195
int rsnd_dai_id(struct rsnd_priv *priv, struct rsnd_dai *rdai);
196
#define rsnd_dai_get_platform_info(rdai) ((rdai)->info)
197
#define rsnd_io_to_runtime(io) ((io)->substream->runtime)
198 199 200 201

void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
/*
 *	R-Car Gen1/Gen2
 */
int rsnd_gen_probe(struct platform_device *pdev,
		   struct rcar_snd_info *info,
		   struct rsnd_priv *priv);
void rsnd_gen_remove(struct platform_device *pdev,
		     struct rsnd_priv *priv);
int rsnd_gen_path_init(struct rsnd_priv *priv,
		       struct rsnd_dai *rdai,
		       struct rsnd_dai_stream *io);
int rsnd_gen_path_exit(struct rsnd_priv *priv,
		       struct rsnd_dai *rdai,
		       struct rsnd_dai_stream *io);
void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
			       struct rsnd_mod *mod,
			       enum rsnd_reg reg);
219 220
#define rsnd_is_gen1(s)		(((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1)
#define rsnd_is_gen2(s)		(((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2)
221

222 223 224 225 226 227 228 229 230 231 232
/*
 *	R-Car ADG
 */
int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod);
int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate);
int rsnd_adg_probe(struct platform_device *pdev,
		   struct rcar_snd_info *info,
		   struct rsnd_priv *priv);
void rsnd_adg_remove(struct platform_device *pdev,
		   struct rsnd_priv *priv);

233 234 235 236 237 238 239 240 241
/*
 *	R-Car sound priv
 */
struct rsnd_priv {

	struct device *dev;
	struct rcar_snd_info *info;
	spinlock_t lock;

242 243 244 245 246
	/*
	 * below value will be filled on rsnd_gen_probe()
	 */
	void *gen;

247 248 249 250 251 252
	/*
	 * below value will be filled on rsnd_scu_probe()
	 */
	void *scu;
	int scu_nr;

253 254 255 256 257
	/*
	 * below value will be filled on rsnd_adg_probe()
	 */
	void *adg;

258 259 260 261 262
	/*
	 * below value will be filled on rsnd_ssi_probe()
	 */
	void *ssiu;

263 264 265 266 267 268 269 270 271 272 273 274
	/*
	 * below value will be filled on rsnd_dai_probe()
	 */
	struct snd_soc_dai_driver *daidrv;
	struct rsnd_dai *rdai;
	int dai_nr;
};

#define rsnd_priv_to_dev(priv)	((priv)->dev)
#define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
#define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags)

275 276 277 278 279 280 281 282 283
/*
 *	R-Car SCU
 */
int rsnd_scu_probe(struct platform_device *pdev,
		   struct rcar_snd_info *info,
		   struct rsnd_priv *priv);
void rsnd_scu_remove(struct platform_device *pdev,
		     struct rsnd_priv *priv);
struct rsnd_mod *rsnd_scu_mod_get(struct rsnd_priv *priv, int id);
284
bool rsnd_scu_hpbif_is_enable(struct rsnd_mod *mod);
285 286
#define rsnd_scu_nr(priv) ((priv)->scu_nr)

287 288 289 290 291 292 293 294 295
/*
 *	R-Car SSI
 */
int rsnd_ssi_probe(struct platform_device *pdev,
		   struct rcar_snd_info *info,
		   struct rsnd_priv *priv);
void rsnd_ssi_remove(struct platform_device *pdev,
		   struct rsnd_priv *priv);
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
296 297
struct rsnd_mod *rsnd_ssi_mod_get_frm_dai(struct rsnd_priv *priv,
					  int dai_id, int is_play);
298

299
#endif