2013-07-22 11:35:52 +07:00
|
|
|
/*
|
|
|
|
* 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>
|
2013-07-29 08:58:50 +07:00
|
|
|
#include <linux/dma-mapping.h>
|
2013-07-22 11:35:52 +07:00
|
|
|
#include <linux/io.h>
|
|
|
|
#include <linux/list.h>
|
|
|
|
#include <linux/module.h>
|
2014-03-18 09:29:55 +07:00
|
|
|
#include <linux/of_device.h>
|
|
|
|
#include <linux/of_irq.h>
|
2013-07-29 08:58:50 +07:00
|
|
|
#include <linux/sh_dma.h>
|
|
|
|
#include <linux/workqueue.h>
|
2013-07-22 11:35:52 +07:00
|
|
|
#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
|
|
|
|
*/
|
2013-07-22 11:36:21 +07:00
|
|
|
enum rsnd_reg {
|
2013-11-29 09:43:45 +07:00
|
|
|
/* SRU/SCU/SSIU */
|
2013-07-22 11:36:35 +07:00
|
|
|
RSND_REG_SSI_MODE0,
|
|
|
|
RSND_REG_SSI_MODE1,
|
2014-01-24 09:37:39 +07:00
|
|
|
RSND_REG_SRC_BUSIF_MODE,
|
2013-12-20 10:28:51 +07:00
|
|
|
RSND_REG_SRC_ROUTE_MODE0,
|
|
|
|
RSND_REG_SRC_SWRSR,
|
|
|
|
RSND_REG_SRC_SRCIR,
|
2013-12-20 10:27:03 +07:00
|
|
|
RSND_REG_SRC_ADINR,
|
2013-12-20 10:28:51 +07:00
|
|
|
RSND_REG_SRC_IFSCR,
|
|
|
|
RSND_REG_SRC_IFSVR,
|
|
|
|
RSND_REG_SRC_SRCCR,
|
2015-01-08 08:52:36 +07:00
|
|
|
RSND_REG_SCU_SYS_STATUS0,
|
|
|
|
RSND_REG_SCU_SYS_INT_EN0,
|
2014-05-09 07:44:49 +07:00
|
|
|
RSND_REG_CMD_ROUTE_SLCT,
|
|
|
|
RSND_REG_DVC_SWRSR,
|
|
|
|
RSND_REG_DVC_DVUIR,
|
|
|
|
RSND_REG_DVC_ADINR,
|
|
|
|
RSND_REG_DVC_DVUCR,
|
|
|
|
RSND_REG_DVC_ZCMCR,
|
|
|
|
RSND_REG_DVC_VOL0R,
|
|
|
|
RSND_REG_DVC_VOL1R,
|
|
|
|
RSND_REG_DVC_DVUER,
|
2013-07-22 11:36:35 +07:00
|
|
|
|
2013-07-22 11:36:46 +07:00
|
|
|
/* ADG */
|
|
|
|
RSND_REG_BRRA,
|
|
|
|
RSND_REG_BRRB,
|
|
|
|
RSND_REG_SSICKR,
|
|
|
|
RSND_REG_AUDIO_CLK_SEL0,
|
|
|
|
RSND_REG_AUDIO_CLK_SEL1,
|
|
|
|
|
2013-07-22 11:36:57 +07:00
|
|
|
/* SSI */
|
|
|
|
RSND_REG_SSICR,
|
|
|
|
RSND_REG_SSISR,
|
|
|
|
RSND_REG_SSITDR,
|
|
|
|
RSND_REG_SSIRDR,
|
|
|
|
RSND_REG_SSIWSR,
|
|
|
|
|
2014-03-03 14:43:40 +07:00
|
|
|
/* SHARE see below */
|
|
|
|
RSND_REG_SHARE01,
|
|
|
|
RSND_REG_SHARE02,
|
|
|
|
RSND_REG_SHARE03,
|
|
|
|
RSND_REG_SHARE04,
|
|
|
|
RSND_REG_SHARE05,
|
|
|
|
RSND_REG_SHARE06,
|
|
|
|
RSND_REG_SHARE07,
|
|
|
|
RSND_REG_SHARE08,
|
|
|
|
RSND_REG_SHARE09,
|
|
|
|
RSND_REG_SHARE10,
|
|
|
|
RSND_REG_SHARE11,
|
|
|
|
RSND_REG_SHARE12,
|
|
|
|
RSND_REG_SHARE13,
|
|
|
|
RSND_REG_SHARE14,
|
|
|
|
RSND_REG_SHARE15,
|
|
|
|
RSND_REG_SHARE16,
|
|
|
|
RSND_REG_SHARE17,
|
|
|
|
RSND_REG_SHARE18,
|
|
|
|
RSND_REG_SHARE19,
|
2014-05-09 07:44:49 +07:00
|
|
|
RSND_REG_SHARE20,
|
|
|
|
RSND_REG_SHARE21,
|
2014-07-31 13:52:26 +07:00
|
|
|
RSND_REG_SHARE22,
|
2014-11-10 10:52:06 +07:00
|
|
|
RSND_REG_SHARE23,
|
|
|
|
RSND_REG_SHARE24,
|
|
|
|
RSND_REG_SHARE25,
|
2015-01-08 08:52:36 +07:00
|
|
|
RSND_REG_SHARE26,
|
|
|
|
RSND_REG_SHARE27,
|
|
|
|
RSND_REG_SHARE28,
|
2014-03-03 14:43:40 +07:00
|
|
|
|
2013-07-22 11:36:21 +07:00
|
|
|
RSND_REG_MAX,
|
|
|
|
};
|
|
|
|
|
2014-03-03 14:43:40 +07:00
|
|
|
/* Gen1 only */
|
|
|
|
#define RSND_REG_SRC_ROUTE_SEL RSND_REG_SHARE01
|
|
|
|
#define RSND_REG_SRC_TMG_SEL0 RSND_REG_SHARE02
|
|
|
|
#define RSND_REG_SRC_TMG_SEL1 RSND_REG_SHARE03
|
|
|
|
#define RSND_REG_SRC_TMG_SEL2 RSND_REG_SHARE04
|
|
|
|
#define RSND_REG_SRC_ROUTE_CTRL RSND_REG_SHARE05
|
|
|
|
#define RSND_REG_SRC_MNFSR RSND_REG_SHARE06
|
|
|
|
#define RSND_REG_AUDIO_CLK_SEL3 RSND_REG_SHARE07
|
|
|
|
#define RSND_REG_AUDIO_CLK_SEL4 RSND_REG_SHARE08
|
|
|
|
#define RSND_REG_AUDIO_CLK_SEL5 RSND_REG_SHARE09
|
|
|
|
|
|
|
|
/* Gen2 only */
|
|
|
|
#define RSND_REG_SRC_CTRL RSND_REG_SHARE01
|
|
|
|
#define RSND_REG_SSI_CTRL RSND_REG_SHARE02
|
|
|
|
#define RSND_REG_SSI_BUSIF_MODE RSND_REG_SHARE03
|
|
|
|
#define RSND_REG_SSI_BUSIF_ADINR RSND_REG_SHARE04
|
|
|
|
#define RSND_REG_INT_ENABLE RSND_REG_SHARE05
|
|
|
|
#define RSND_REG_SRC_BSDSR RSND_REG_SHARE06
|
|
|
|
#define RSND_REG_SRC_BSISR RSND_REG_SHARE07
|
|
|
|
#define RSND_REG_DIV_EN RSND_REG_SHARE08
|
|
|
|
#define RSND_REG_SRCIN_TIMSEL0 RSND_REG_SHARE09
|
|
|
|
#define RSND_REG_SRCIN_TIMSEL1 RSND_REG_SHARE10
|
|
|
|
#define RSND_REG_SRCIN_TIMSEL2 RSND_REG_SHARE11
|
|
|
|
#define RSND_REG_SRCIN_TIMSEL3 RSND_REG_SHARE12
|
|
|
|
#define RSND_REG_SRCIN_TIMSEL4 RSND_REG_SHARE13
|
|
|
|
#define RSND_REG_SRCOUT_TIMSEL0 RSND_REG_SHARE14
|
|
|
|
#define RSND_REG_SRCOUT_TIMSEL1 RSND_REG_SHARE15
|
|
|
|
#define RSND_REG_SRCOUT_TIMSEL2 RSND_REG_SHARE16
|
|
|
|
#define RSND_REG_SRCOUT_TIMSEL3 RSND_REG_SHARE17
|
|
|
|
#define RSND_REG_SRCOUT_TIMSEL4 RSND_REG_SHARE18
|
|
|
|
#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19
|
2014-05-09 07:44:49 +07:00
|
|
|
#define RSND_REG_CMD_CTRL RSND_REG_SHARE20
|
|
|
|
#define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21
|
2014-07-31 13:52:26 +07:00
|
|
|
#define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22
|
2014-11-10 10:52:06 +07:00
|
|
|
#define RSND_REG_DVC_VRCTR RSND_REG_SHARE23
|
|
|
|
#define RSND_REG_DVC_VRPDR RSND_REG_SHARE24
|
|
|
|
#define RSND_REG_DVC_VRDBR RSND_REG_SHARE25
|
2015-01-08 08:52:36 +07:00
|
|
|
#define RSND_REG_SCU_SYS_STATUS1 RSND_REG_SHARE26
|
|
|
|
#define RSND_REG_SCU_SYS_INT_EN1 RSND_REG_SHARE27
|
|
|
|
#define RSND_REG_SRC_INT_ENABLE0 RSND_REG_SHARE28
|
2014-03-03 14:43:40 +07:00
|
|
|
|
2014-03-18 09:29:55 +07:00
|
|
|
struct rsnd_of_data;
|
2013-07-22 11:35:52 +07:00
|
|
|
struct rsnd_priv;
|
2013-07-22 11:36:03 +07:00
|
|
|
struct rsnd_mod;
|
2013-07-22 11:35:52 +07:00
|
|
|
struct rsnd_dai;
|
|
|
|
struct rsnd_dai_stream;
|
|
|
|
|
2013-07-22 11:36:21 +07:00
|
|
|
/*
|
|
|
|
* 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);
|
2014-05-09 07:44:14 +07:00
|
|
|
u32 rsnd_get_adinr(struct rsnd_mod *mod);
|
2013-07-22 11:36:21 +07:00
|
|
|
|
2013-07-29 08:58:50 +07:00
|
|
|
/*
|
|
|
|
* R-Car DMA
|
|
|
|
*/
|
2015-02-20 17:27:12 +07:00
|
|
|
struct rsnd_dma;
|
|
|
|
struct rsnd_dma_ops {
|
|
|
|
void (*start)(struct rsnd_dma *dma);
|
|
|
|
void (*stop)(struct rsnd_dma *dma);
|
|
|
|
int (*init)(struct rsnd_priv *priv, struct rsnd_dma *dma, int id,
|
|
|
|
struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
|
|
|
|
void (*quit)(struct rsnd_dma *dma);
|
|
|
|
};
|
|
|
|
|
2015-02-20 17:29:13 +07:00
|
|
|
struct rsnd_dmaen {
|
2013-07-29 08:58:50 +07:00
|
|
|
struct dma_chan *chan;
|
2015-02-20 17:29:13 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct rsnd_dmapp {
|
2015-02-20 17:27:42 +07:00
|
|
|
int dmapp_id;
|
|
|
|
u32 chcr;
|
2015-02-20 17:29:13 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
struct rsnd_dma {
|
|
|
|
struct rsnd_dma_ops *ops;
|
2015-02-20 17:27:12 +07:00
|
|
|
dma_addr_t src_addr;
|
|
|
|
dma_addr_t dst_addr;
|
2015-02-20 17:29:13 +07:00
|
|
|
union {
|
|
|
|
struct rsnd_dmaen en;
|
|
|
|
struct rsnd_dmapp pp;
|
|
|
|
} dma;
|
2013-07-29 08:58:50 +07:00
|
|
|
};
|
2015-02-20 17:29:13 +07:00
|
|
|
#define rsnd_dma_to_dmaen(dma) (&(dma)->dma.en)
|
|
|
|
#define rsnd_dma_to_dmapp(dma) (&(dma)->dma.pp)
|
2013-07-29 08:58:50 +07:00
|
|
|
|
|
|
|
void rsnd_dma_start(struct rsnd_dma *dma);
|
|
|
|
void rsnd_dma_stop(struct rsnd_dma *dma);
|
2015-02-20 17:23:08 +07:00
|
|
|
int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma, int id);
|
2015-02-20 17:24:06 +07:00
|
|
|
void rsnd_dma_quit(struct rsnd_dma *dma);
|
2015-02-20 17:27:42 +07:00
|
|
|
int rsnd_dma_probe(struct platform_device *pdev,
|
|
|
|
const struct rsnd_of_data *of_data,
|
|
|
|
struct rsnd_priv *priv);
|
ASoC: rsnd: 1st DMAC dma-names cares subnode
Renesas R-Car sound (= rsnd) needs 2 DMAC which are called as
Audio DMAC (= 1st DMAC) and Audio DMAC peri peri (2nd DMAC).
And rsnd had assumed that 1st / 2nd DMACs are implemented as DMAEngine.
But, in result of DMA ML discussion, 2nd DMAC was concluded that it is
not a general purpose DMAC (2nd DMAC is for Device to Device inside
sound system). Additionally, current DMAEngine can't support Device to
Device, and we don't have correct DT bindings for it at this point.
So the easiest solution for it is that move it from DMAEngine to rsnd
driver.
dma-names on DT was implemented as no difference between 1st / 2nd
DMAC's, since rsnd had assumed that both DMACs are implemented as
DMAEngine. That style was "src_dst". But now, 2nd DMAC was implemented
as non DMAEngine, and it doesn't need dma-names anymore. So, this
dma-names rule is no longer needed.
And additionally, dma-names was assumed that it has all
(= SSI/SSIU/SRC/DVC) nodes under sound node.
In upstream code, no SoC/platform is supporting DMA for rsnd driver yet.
This means there is no compatible issue if this patch changes
dma-names's rule of DT.
This patch assumes dma-names for 1st DMAC are tx/rx base, and listed
in each SSI/SRC/DVC subnode
ex)
rcar_sound,dvc {
dvc0: dvc@0 {
dmas = <&audma0 0xbc>;
dma-names = "tx";
};
...
rcar_sound,src {
src0: src@0 {
...
dmas = <&audma0 0x85>, <&audma1 0x9a>;
dma-names = "rx", "tx";
};
...
rcar_sound,ssi {
ssi0: ssi@0 {
...
dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>;
dma-names = "rx", "tx", "rxu", "txu";
};
...
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2015-02-20 17:31:23 +07:00
|
|
|
struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
|
|
|
|
struct rsnd_mod *mod, char *name);
|
2013-07-29 08:58:50 +07:00
|
|
|
|
2015-02-20 17:24:27 +07:00
|
|
|
#define rsnd_dma_to_mod(_dma) container_of((_dma), struct rsnd_mod, dma)
|
|
|
|
|
2013-07-22 11:36:03 +07:00
|
|
|
/*
|
|
|
|
* R-Car sound mod
|
|
|
|
*/
|
2014-03-03 14:42:55 +07:00
|
|
|
enum rsnd_mod_type {
|
2015-01-15 15:09:44 +07:00
|
|
|
RSND_MOD_DVC = 0,
|
|
|
|
RSND_MOD_SRC,
|
2014-03-03 14:42:55 +07:00
|
|
|
RSND_MOD_SSI,
|
|
|
|
RSND_MOD_MAX,
|
|
|
|
};
|
2013-07-22 11:36:03 +07:00
|
|
|
|
|
|
|
struct rsnd_mod_ops {
|
|
|
|
char *name;
|
ASoC: rsnd: 1st DMAC dma-names cares subnode
Renesas R-Car sound (= rsnd) needs 2 DMAC which are called as
Audio DMAC (= 1st DMAC) and Audio DMAC peri peri (2nd DMAC).
And rsnd had assumed that 1st / 2nd DMACs are implemented as DMAEngine.
But, in result of DMA ML discussion, 2nd DMAC was concluded that it is
not a general purpose DMAC (2nd DMAC is for Device to Device inside
sound system). Additionally, current DMAEngine can't support Device to
Device, and we don't have correct DT bindings for it at this point.
So the easiest solution for it is that move it from DMAEngine to rsnd
driver.
dma-names on DT was implemented as no difference between 1st / 2nd
DMAC's, since rsnd had assumed that both DMACs are implemented as
DMAEngine. That style was "src_dst". But now, 2nd DMAC was implemented
as non DMAEngine, and it doesn't need dma-names anymore. So, this
dma-names rule is no longer needed.
And additionally, dma-names was assumed that it has all
(= SSI/SSIU/SRC/DVC) nodes under sound node.
In upstream code, no SoC/platform is supporting DMA for rsnd driver yet.
This means there is no compatible issue if this patch changes
dma-names's rule of DT.
This patch assumes dma-names for 1st DMAC are tx/rx base, and listed
in each SSI/SRC/DVC subnode
ex)
rcar_sound,dvc {
dvc0: dvc@0 {
dmas = <&audma0 0xbc>;
dma-names = "tx";
};
...
rcar_sound,src {
src0: src@0 {
...
dmas = <&audma0 0x85>, <&audma1 0x9a>;
dma-names = "rx", "tx";
};
...
rcar_sound,ssi {
ssi0: ssi@0 {
...
dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>;
dma-names = "rx", "tx", "rxu", "txu";
};
...
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2015-02-20 17:31:23 +07:00
|
|
|
struct dma_chan* (*dma_req)(struct rsnd_mod *mod);
|
2014-03-04 11:50:33 +07:00
|
|
|
int (*probe)(struct rsnd_mod *mod,
|
2015-01-15 15:07:47 +07:00
|
|
|
struct rsnd_priv *priv);
|
2014-03-04 11:50:33 +07:00
|
|
|
int (*remove)(struct rsnd_mod *mod,
|
2015-01-15 15:07:47 +07:00
|
|
|
struct rsnd_priv *priv);
|
2013-07-22 11:36:03 +07:00
|
|
|
int (*init)(struct rsnd_mod *mod,
|
2015-01-15 15:07:47 +07:00
|
|
|
struct rsnd_priv *priv);
|
2013-07-22 11:36:03 +07:00
|
|
|
int (*quit)(struct rsnd_mod *mod,
|
2015-01-15 15:07:47 +07:00
|
|
|
struct rsnd_priv *priv);
|
2013-07-22 11:36:03 +07:00
|
|
|
int (*start)(struct rsnd_mod *mod,
|
2015-01-15 15:07:47 +07:00
|
|
|
struct rsnd_priv *priv);
|
2013-07-22 11:36:03 +07:00
|
|
|
int (*stop)(struct rsnd_mod *mod,
|
2015-01-15 15:07:47 +07:00
|
|
|
struct rsnd_priv *priv);
|
2014-05-09 07:44:49 +07:00
|
|
|
int (*pcm_new)(struct rsnd_mod *mod,
|
|
|
|
struct snd_soc_pcm_runtime *rtd);
|
2014-11-27 15:02:43 +07:00
|
|
|
int (*fallback)(struct rsnd_mod *mod,
|
2015-01-15 15:07:47 +07:00
|
|
|
struct rsnd_priv *priv);
|
2013-07-22 11:36:03 +07:00
|
|
|
};
|
|
|
|
|
2014-01-24 09:41:44 +07:00
|
|
|
struct rsnd_dai_stream;
|
2013-07-22 11:36:03 +07:00
|
|
|
struct rsnd_mod {
|
|
|
|
int id;
|
2014-03-03 14:42:55 +07:00
|
|
|
enum rsnd_mod_type type;
|
2013-07-22 11:36:03 +07:00
|
|
|
struct rsnd_mod_ops *ops;
|
2013-07-29 08:58:50 +07:00
|
|
|
struct rsnd_dma dma;
|
2014-01-24 09:41:44 +07:00
|
|
|
struct rsnd_dai_stream *io;
|
2015-01-15 15:03:22 +07:00
|
|
|
struct clk *clk;
|
2014-11-27 15:02:55 +07:00
|
|
|
u32 status;
|
2013-07-22 11:36:03 +07:00
|
|
|
};
|
2014-11-27 15:02:55 +07:00
|
|
|
/*
|
|
|
|
* status
|
|
|
|
*
|
|
|
|
* bit
|
|
|
|
* 0 0: probe 1: remove
|
|
|
|
* 1 0: init 1: quit
|
|
|
|
* 2 0: start 1: stop
|
|
|
|
* 3 0: pcm_new
|
|
|
|
* 4 0: fallback
|
|
|
|
*/
|
|
|
|
#define __rsnd_mod_shift_probe 0
|
|
|
|
#define __rsnd_mod_shift_remove 0
|
|
|
|
#define __rsnd_mod_shift_init 1
|
|
|
|
#define __rsnd_mod_shift_quit 1
|
|
|
|
#define __rsnd_mod_shift_start 2
|
|
|
|
#define __rsnd_mod_shift_stop 2
|
|
|
|
#define __rsnd_mod_shift_pcm_new 3
|
|
|
|
#define __rsnd_mod_shift_fallback 4
|
|
|
|
|
|
|
|
#define __rsnd_mod_call_probe 0
|
|
|
|
#define __rsnd_mod_call_remove 1
|
|
|
|
#define __rsnd_mod_call_init 0
|
|
|
|
#define __rsnd_mod_call_quit 1
|
|
|
|
#define __rsnd_mod_call_start 0
|
|
|
|
#define __rsnd_mod_call_stop 1
|
|
|
|
#define __rsnd_mod_call_pcm_new 0
|
|
|
|
#define __rsnd_mod_call_fallback 0
|
2013-07-22 11:36:03 +07:00
|
|
|
|
2015-01-15 15:08:34 +07:00
|
|
|
#define rsnd_mod_to_priv(mod) (rsnd_io_to_priv(rsnd_mod_to_io(mod)))
|
2013-07-29 08:58:50 +07:00
|
|
|
#define rsnd_mod_to_dma(mod) (&(mod)->dma)
|
2014-01-24 09:41:44 +07:00
|
|
|
#define rsnd_mod_to_io(mod) ((mod)->io)
|
2013-07-22 11:36:03 +07:00
|
|
|
#define rsnd_mod_id(mod) ((mod)->id)
|
2015-01-15 15:03:22 +07:00
|
|
|
#define rsnd_mod_hw_start(mod) clk_prepare_enable((mod)->clk)
|
|
|
|
#define rsnd_mod_hw_stop(mod) clk_disable_unprepare((mod)->clk)
|
2013-07-22 11:36:03 +07:00
|
|
|
|
2015-01-15 15:08:34 +07:00
|
|
|
void rsnd_mod_init(struct rsnd_mod *mod,
|
2013-07-22 11:36:03 +07:00
|
|
|
struct rsnd_mod_ops *ops,
|
2015-01-15 15:03:22 +07:00
|
|
|
struct clk *clk,
|
2014-03-03 14:42:55 +07:00
|
|
|
enum rsnd_mod_type type,
|
2013-07-22 11:36:03 +07:00
|
|
|
int id);
|
|
|
|
char *rsnd_mod_name(struct rsnd_mod *mod);
|
ASoC: rsnd: 1st DMAC dma-names cares subnode
Renesas R-Car sound (= rsnd) needs 2 DMAC which are called as
Audio DMAC (= 1st DMAC) and Audio DMAC peri peri (2nd DMAC).
And rsnd had assumed that 1st / 2nd DMACs are implemented as DMAEngine.
But, in result of DMA ML discussion, 2nd DMAC was concluded that it is
not a general purpose DMAC (2nd DMAC is for Device to Device inside
sound system). Additionally, current DMAEngine can't support Device to
Device, and we don't have correct DT bindings for it at this point.
So the easiest solution for it is that move it from DMAEngine to rsnd
driver.
dma-names on DT was implemented as no difference between 1st / 2nd
DMAC's, since rsnd had assumed that both DMACs are implemented as
DMAEngine. That style was "src_dst". But now, 2nd DMAC was implemented
as non DMAEngine, and it doesn't need dma-names anymore. So, this
dma-names rule is no longer needed.
And additionally, dma-names was assumed that it has all
(= SSI/SSIU/SRC/DVC) nodes under sound node.
In upstream code, no SoC/platform is supporting DMA for rsnd driver yet.
This means there is no compatible issue if this patch changes
dma-names's rule of DT.
This patch assumes dma-names for 1st DMAC are tx/rx base, and listed
in each SSI/SRC/DVC subnode
ex)
rcar_sound,dvc {
dvc0: dvc@0 {
dmas = <&audma0 0xbc>;
dma-names = "tx";
};
...
rcar_sound,src {
src0: src@0 {
...
dmas = <&audma0 0x85>, <&audma1 0x9a>;
dma-names = "rx", "tx";
};
...
rcar_sound,ssi {
ssi0: ssi@0 {
...
dmas = <&audma0 0x01>, <&audma1 0x02>, <&audma0 0x15>, <&audma1 0x16>;
dma-names = "rx", "tx", "rxu", "txu";
};
...
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
2015-02-20 17:31:23 +07:00
|
|
|
struct dma_chan *rsnd_mod_dma_req(struct rsnd_mod *mod);
|
2013-07-22 11:36:03 +07:00
|
|
|
|
2013-07-22 11:35:52 +07:00
|
|
|
/*
|
|
|
|
* R-Car sound DAI
|
|
|
|
*/
|
|
|
|
#define RSND_DAI_NAME_SIZE 16
|
|
|
|
struct rsnd_dai_stream {
|
|
|
|
struct snd_pcm_substream *substream;
|
2014-03-03 14:42:55 +07:00
|
|
|
struct rsnd_mod *mod[RSND_MOD_MAX];
|
2014-03-04 11:50:00 +07:00
|
|
|
struct rsnd_dai_path_info *info; /* rcar_snd.h */
|
2015-01-15 15:06:24 +07:00
|
|
|
struct rsnd_dai *rdai;
|
2013-07-22 11:35:52 +07:00
|
|
|
int byte_pos;
|
|
|
|
int period_pos;
|
|
|
|
int byte_per_period;
|
|
|
|
int next_period_byte;
|
|
|
|
};
|
2014-03-03 14:43:03 +07:00
|
|
|
#define rsnd_io_to_mod_ssi(io) ((io)->mod[RSND_MOD_SSI])
|
2014-03-04 11:51:21 +07:00
|
|
|
#define rsnd_io_to_mod_src(io) ((io)->mod[RSND_MOD_SRC])
|
2014-05-09 07:44:49 +07:00
|
|
|
#define rsnd_io_to_mod_dvc(io) ((io)->mod[RSND_MOD_DVC])
|
2015-01-15 15:06:24 +07:00
|
|
|
#define rsnd_io_to_rdai(io) ((io)->rdai)
|
2015-01-15 15:08:34 +07:00
|
|
|
#define rsnd_io_to_priv(io) (rsnd_rdai_to_priv(rsnd_io_to_rdai(io)))
|
2015-01-15 15:06:49 +07:00
|
|
|
#define rsnd_io_is_play(io) (&rsnd_io_to_rdai(io)->playback == io)
|
2015-01-15 15:02:40 +07:00
|
|
|
#define rsnd_io_to_runtime(io) ((io)->substream ? \
|
|
|
|
(io)->substream->runtime : NULL)
|
2013-07-22 11:35:52 +07:00
|
|
|
|
2015-01-15 15:06:49 +07:00
|
|
|
|
2013-07-22 11:35:52 +07:00
|
|
|
struct rsnd_dai {
|
|
|
|
char name[RSND_DAI_NAME_SIZE];
|
|
|
|
struct rsnd_dai_stream playback;
|
|
|
|
struct rsnd_dai_stream capture;
|
2015-01-15 15:08:34 +07:00
|
|
|
struct rsnd_priv *priv;
|
2013-07-22 11:35:52 +07:00
|
|
|
|
2013-11-08 16:46:53 +07:00
|
|
|
unsigned int clk_master:1;
|
|
|
|
unsigned int bit_clk_inv:1;
|
|
|
|
unsigned int frm_clk_inv:1;
|
|
|
|
unsigned int sys_delay:1;
|
|
|
|
unsigned int data_alignment:1;
|
2013-07-22 11:35:52 +07:00
|
|
|
};
|
|
|
|
|
2014-02-25 13:15:18 +07:00
|
|
|
#define rsnd_rdai_nr(priv) ((priv)->rdai_nr)
|
2015-01-15 15:04:51 +07:00
|
|
|
#define rsnd_rdai_is_clk_master(rdai) ((rdai)->clk_master)
|
2015-01-15 15:08:34 +07:00
|
|
|
#define rsnd_rdai_to_priv(rdai) ((rdai)->priv)
|
2013-07-22 11:35:52 +07:00
|
|
|
#define for_each_rsnd_dai(rdai, priv, i) \
|
2014-02-12 08:15:51 +07:00
|
|
|
for (i = 0; \
|
2014-02-25 13:15:18 +07:00
|
|
|
(i < rsnd_rdai_nr(priv)) && \
|
2015-01-15 15:03:38 +07:00
|
|
|
((rdai) = rsnd_rdai_get(priv, i)); \
|
2014-02-12 08:15:51 +07:00
|
|
|
i++)
|
2013-07-22 11:35:52 +07:00
|
|
|
|
2015-01-15 15:03:38 +07:00
|
|
|
struct rsnd_dai *rsnd_rdai_get(struct rsnd_priv *priv, int id);
|
|
|
|
|
2013-07-22 11:35:52 +07:00
|
|
|
void rsnd_dai_pointer_update(struct rsnd_dai_stream *io, int cnt);
|
|
|
|
int rsnd_dai_pointer_offset(struct rsnd_dai_stream *io, int additional);
|
|
|
|
|
2013-07-22 11:36:21 +07:00
|
|
|
/*
|
|
|
|
* R-Car Gen1/Gen2
|
|
|
|
*/
|
|
|
|
int rsnd_gen_probe(struct platform_device *pdev,
|
2014-03-18 09:29:55 +07:00
|
|
|
const struct rsnd_of_data *of_data,
|
2013-07-22 11:36:21 +07:00
|
|
|
struct rsnd_priv *priv);
|
|
|
|
void __iomem *rsnd_gen_reg_get(struct rsnd_priv *priv,
|
|
|
|
struct rsnd_mod *mod,
|
|
|
|
enum rsnd_reg reg);
|
2015-02-20 17:25:27 +07:00
|
|
|
phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id);
|
2014-05-23 13:25:54 +07:00
|
|
|
|
2013-10-11 14:07:01 +07:00
|
|
|
#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)
|
2013-07-22 11:36:21 +07:00
|
|
|
|
2013-07-22 11:36:46 +07:00
|
|
|
/*
|
|
|
|
* 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,
|
2014-03-18 09:29:55 +07:00
|
|
|
const struct rsnd_of_data *of_data,
|
2013-07-22 11:36:46 +07:00
|
|
|
struct rsnd_priv *priv);
|
2014-01-24 09:41:10 +07:00
|
|
|
int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
|
|
|
|
struct rsnd_mod *mod,
|
|
|
|
unsigned int src_rate,
|
|
|
|
unsigned int dst_rate);
|
2014-01-24 09:42:00 +07:00
|
|
|
int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
|
|
|
|
struct rsnd_dai_stream *io,
|
|
|
|
unsigned int src_rate,
|
|
|
|
unsigned int dst_rate);
|
|
|
|
int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod,
|
|
|
|
struct rsnd_dai_stream *io);
|
2015-01-15 15:07:19 +07:00
|
|
|
int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod,
|
2014-05-09 07:44:49 +07:00
|
|
|
struct rsnd_dai_stream *io);
|
2013-07-22 11:36:46 +07:00
|
|
|
|
2013-07-22 11:35:52 +07:00
|
|
|
/*
|
|
|
|
* R-Car sound priv
|
|
|
|
*/
|
2014-03-18 09:29:55 +07:00
|
|
|
struct rsnd_of_data {
|
|
|
|
u32 flags;
|
|
|
|
};
|
|
|
|
|
2013-07-22 11:35:52 +07:00
|
|
|
struct rsnd_priv {
|
|
|
|
|
2014-05-23 13:25:30 +07:00
|
|
|
struct platform_device *pdev;
|
2013-07-22 11:35:52 +07:00
|
|
|
struct rcar_snd_info *info;
|
|
|
|
spinlock_t lock;
|
|
|
|
|
2013-07-22 11:36:21 +07:00
|
|
|
/*
|
|
|
|
* below value will be filled on rsnd_gen_probe()
|
|
|
|
*/
|
|
|
|
void *gen;
|
|
|
|
|
2013-07-22 11:36:35 +07:00
|
|
|
/*
|
2014-03-04 11:51:21 +07:00
|
|
|
* below value will be filled on rsnd_src_probe()
|
2013-07-22 11:36:35 +07:00
|
|
|
*/
|
2014-03-04 11:51:21 +07:00
|
|
|
void *src;
|
|
|
|
int src_nr;
|
2013-07-22 11:36:35 +07:00
|
|
|
|
2013-07-22 11:36:46 +07:00
|
|
|
/*
|
|
|
|
* below value will be filled on rsnd_adg_probe()
|
|
|
|
*/
|
|
|
|
void *adg;
|
|
|
|
|
2015-02-20 17:27:42 +07:00
|
|
|
/*
|
|
|
|
* below value will be filled on rsnd_dma_probe()
|
|
|
|
*/
|
|
|
|
void *dma;
|
|
|
|
|
2013-07-22 11:36:57 +07:00
|
|
|
/*
|
|
|
|
* below value will be filled on rsnd_ssi_probe()
|
|
|
|
*/
|
2014-01-24 09:39:40 +07:00
|
|
|
void *ssi;
|
|
|
|
int ssi_nr;
|
2013-07-22 11:36:57 +07:00
|
|
|
|
2014-05-09 07:44:49 +07:00
|
|
|
/*
|
|
|
|
* below value will be filled on rsnd_dvc_probe()
|
|
|
|
*/
|
|
|
|
void *dvc;
|
|
|
|
int dvc_nr;
|
|
|
|
|
2013-07-22 11:35:52 +07:00
|
|
|
/*
|
|
|
|
* below value will be filled on rsnd_dai_probe()
|
|
|
|
*/
|
|
|
|
struct snd_soc_dai_driver *daidrv;
|
|
|
|
struct rsnd_dai *rdai;
|
2014-02-25 13:15:18 +07:00
|
|
|
int rdai_nr;
|
2013-07-22 11:35:52 +07:00
|
|
|
};
|
|
|
|
|
2014-05-23 13:25:30 +07:00
|
|
|
#define rsnd_priv_to_pdev(priv) ((priv)->pdev)
|
|
|
|
#define rsnd_priv_to_dev(priv) (&(rsnd_priv_to_pdev(priv)->dev))
|
2014-02-25 13:15:00 +07:00
|
|
|
#define rsnd_priv_to_info(priv) ((priv)->info)
|
2013-07-22 11:35:52 +07:00
|
|
|
#define rsnd_lock(priv, flags) spin_lock_irqsave(&priv->lock, flags)
|
|
|
|
#define rsnd_unlock(priv, flags) spin_unlock_irqrestore(&priv->lock, flags)
|
|
|
|
|
2014-11-27 15:06:14 +07:00
|
|
|
/*
|
|
|
|
* rsnd_kctrl
|
|
|
|
*/
|
|
|
|
struct rsnd_kctrl_cfg {
|
|
|
|
unsigned int max;
|
|
|
|
unsigned int size;
|
|
|
|
u32 *val;
|
|
|
|
const char * const *texts;
|
|
|
|
void (*update)(struct rsnd_mod *mod);
|
2015-02-02 11:53:53 +07:00
|
|
|
struct snd_card *card;
|
|
|
|
struct snd_kcontrol *kctrl;
|
2014-11-27 15:06:14 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
#define RSND_DVC_CHANNELS 2
|
|
|
|
struct rsnd_kctrl_cfg_m {
|
|
|
|
struct rsnd_kctrl_cfg cfg;
|
|
|
|
u32 val[RSND_DVC_CHANNELS];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct rsnd_kctrl_cfg_s {
|
|
|
|
struct rsnd_kctrl_cfg cfg;
|
|
|
|
u32 val;
|
|
|
|
};
|
|
|
|
|
2015-02-02 11:53:53 +07:00
|
|
|
void _rsnd_kctrl_remove(struct rsnd_kctrl_cfg *cfg);
|
|
|
|
#define rsnd_kctrl_remove(_cfg) _rsnd_kctrl_remove(&((_cfg).cfg))
|
|
|
|
|
2014-11-27 15:06:14 +07:00
|
|
|
int rsnd_kctrl_new_m(struct rsnd_mod *mod,
|
|
|
|
struct snd_soc_pcm_runtime *rtd,
|
|
|
|
const unsigned char *name,
|
|
|
|
void (*update)(struct rsnd_mod *mod),
|
|
|
|
struct rsnd_kctrl_cfg_m *_cfg,
|
|
|
|
u32 max);
|
|
|
|
int rsnd_kctrl_new_s(struct rsnd_mod *mod,
|
|
|
|
struct snd_soc_pcm_runtime *rtd,
|
|
|
|
const unsigned char *name,
|
|
|
|
void (*update)(struct rsnd_mod *mod),
|
|
|
|
struct rsnd_kctrl_cfg_s *_cfg,
|
|
|
|
u32 max);
|
|
|
|
int rsnd_kctrl_new_e(struct rsnd_mod *mod,
|
|
|
|
struct snd_soc_pcm_runtime *rtd,
|
|
|
|
const unsigned char *name,
|
|
|
|
struct rsnd_kctrl_cfg_s *_cfg,
|
|
|
|
void (*update)(struct rsnd_mod *mod),
|
|
|
|
const char * const *texts,
|
|
|
|
u32 max);
|
|
|
|
|
2013-07-22 11:36:35 +07:00
|
|
|
/*
|
2014-03-04 11:51:21 +07:00
|
|
|
* R-Car SRC
|
2013-07-22 11:36:35 +07:00
|
|
|
*/
|
2014-03-04 11:51:21 +07:00
|
|
|
int rsnd_src_probe(struct platform_device *pdev,
|
2014-03-18 09:29:55 +07:00
|
|
|
const struct rsnd_of_data *of_data,
|
2013-07-22 11:36:35 +07:00
|
|
|
struct rsnd_priv *priv);
|
2014-03-04 11:51:21 +07:00
|
|
|
struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
|
|
|
|
unsigned int rsnd_src_get_ssi_rate(struct rsnd_priv *priv,
|
2014-03-03 14:43:03 +07:00
|
|
|
struct rsnd_dai_stream *io,
|
2013-12-20 10:28:51 +07:00
|
|
|
struct snd_pcm_runtime *runtime);
|
2014-06-23 07:56:23 +07:00
|
|
|
int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod,
|
|
|
|
int use_busif);
|
2015-01-15 15:07:19 +07:00
|
|
|
int rsnd_src_ssiu_stop(struct rsnd_mod *ssi_mod);
|
|
|
|
int rsnd_src_ssi_irq_enable(struct rsnd_mod *ssi_mod);
|
|
|
|
int rsnd_src_ssi_irq_disable(struct rsnd_mod *ssi_mod);
|
2013-12-20 10:28:51 +07:00
|
|
|
|
2014-03-04 11:51:21 +07:00
|
|
|
#define rsnd_src_nr(priv) ((priv)->src_nr)
|
2013-07-22 11:36:35 +07:00
|
|
|
|
2013-07-22 11:36:57 +07:00
|
|
|
/*
|
|
|
|
* R-Car SSI
|
|
|
|
*/
|
|
|
|
int rsnd_ssi_probe(struct platform_device *pdev,
|
2014-03-18 09:29:55 +07:00
|
|
|
const struct rsnd_of_data *of_data,
|
2013-07-22 11:36:57 +07:00
|
|
|
struct rsnd_priv *priv);
|
|
|
|
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
|
2014-01-24 09:39:32 +07:00
|
|
|
int rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod);
|
2014-11-27 15:05:01 +07:00
|
|
|
int rsnd_ssi_is_dma_mode(struct rsnd_mod *mod);
|
2015-02-20 17:29:41 +07:00
|
|
|
int rsnd_ssi_use_busif(struct rsnd_mod *mod);
|
2013-07-22 11:36:57 +07:00
|
|
|
|
2014-05-09 07:44:49 +07:00
|
|
|
/*
|
|
|
|
* R-Car DVC
|
|
|
|
*/
|
|
|
|
int rsnd_dvc_probe(struct platform_device *pdev,
|
|
|
|
const struct rsnd_of_data *of_data,
|
|
|
|
struct rsnd_priv *priv);
|
|
|
|
void rsnd_dvc_remove(struct platform_device *pdev,
|
|
|
|
struct rsnd_priv *priv);
|
|
|
|
struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id);
|
|
|
|
|
|
|
|
#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
|
|
|
|
|
|
|
|
|
2013-07-22 11:35:52 +07:00
|
|
|
#endif
|