blob: 65d3835cffbc66889c7a0387ff08e3a11be7abd9 [file] [log] [blame]
/*
* 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>
#include <linux/io.h>
#include <linux/list.h>
#include <linux/module.h>
#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
*/
struct rsnd_priv;
struct rsnd_mod;
struct rsnd_dai;
struct rsnd_dai_stream;
/*
* 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 */
};
#define rsnd_mod_to_priv(mod) ((mod)->priv)
#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);
/*
* 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);
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);
int rsnd_dai_is_play(struct rsnd_dai *rdai, struct rsnd_dai_stream *io);
#define rsnd_dai_get_platform_info(rdai) ((rdai)->info)
void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
/*
* R-Car sound priv
*/
struct rsnd_priv {
struct device *dev;
struct rcar_snd_info *info;
spinlock_t lock;
/*
* 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)
#endif