Commit b60be4aa authored by Padmavathi Venna's avatar Padmavathi Venna Committed by Mark Brown

ASoC: Samsung: I2S: Modify driver to give more flexibility

This patch modifies the i2s driver to give flexibility towards register
handling. This is a pre requirement for enabling i2s support on Exynos5420.
This patch modifies only the required registers as a pre-requirement to
support on Exynos5420.
Signed-off-by: default avatarPadmavathi Venna <padma.v@samsung.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 7497185f
...@@ -95,22 +95,26 @@ ...@@ -95,22 +95,26 @@
#define MOD_RXONLY (1 << 8) #define MOD_RXONLY (1 << 8)
#define MOD_TXRX (2 << 8) #define MOD_TXRX (2 << 8)
#define MOD_MASK (3 << 8) #define MOD_MASK (3 << 8)
#define MOD_LR_LLOW (0 << 7) #define MOD_LRP_SHIFT 7
#define MOD_LR_RLOW (1 << 7) #define MOD_LR_LLOW 0
#define MOD_SDF_IIS (0 << 5) #define MOD_LR_RLOW 1
#define MOD_SDF_MSB (1 << 5) #define MOD_SDF_SHIFT 5
#define MOD_SDF_LSB (2 << 5) #define MOD_SDF_IIS 0
#define MOD_SDF_MASK (3 << 5) #define MOD_SDF_MSB 1
#define MOD_RCLK_256FS (0 << 3) #define MOD_SDF_LSB 2
#define MOD_RCLK_512FS (1 << 3) #define MOD_SDF_MASK 3
#define MOD_RCLK_384FS (2 << 3) #define MOD_RCLK_SHIFT 3
#define MOD_RCLK_768FS (3 << 3) #define MOD_RCLK_256FS 0
#define MOD_RCLK_MASK (3 << 3) #define MOD_RCLK_512FS 1
#define MOD_BCLK_32FS (0 << 1) #define MOD_RCLK_384FS 2
#define MOD_BCLK_48FS (1 << 1) #define MOD_RCLK_768FS 3
#define MOD_BCLK_16FS (2 << 1) #define MOD_RCLK_MASK 3
#define MOD_BCLK_24FS (3 << 1) #define MOD_BCLK_SHIFT 1
#define MOD_BCLK_MASK (3 << 1) #define MOD_BCLK_32FS 0
#define MOD_BCLK_48FS 1
#define MOD_BCLK_16FS 2
#define MOD_BCLK_24FS 3
#define MOD_BCLK_MASK 3
#define MOD_8BIT (1 << 0) #define MOD_8BIT (1 << 0)
#define MOD_CDCLKCON (1 << 12) #define MOD_CDCLKCON (1 << 12)
......
...@@ -198,7 +198,8 @@ static inline bool is_manager(struct i2s_dai *i2s) ...@@ -198,7 +198,8 @@ static inline bool is_manager(struct i2s_dai *i2s)
/* Read RCLK of I2S (in multiples of LRCLK) */ /* Read RCLK of I2S (in multiples of LRCLK) */
static inline unsigned get_rfs(struct i2s_dai *i2s) static inline unsigned get_rfs(struct i2s_dai *i2s)
{ {
u32 rfs = (readl(i2s->addr + I2SMOD) >> 3) & 0x3; u32 rfs = (readl(i2s->addr + I2SMOD) >> MOD_RCLK_SHIFT);
rfs &= MOD_RCLK_MASK;
switch (rfs) { switch (rfs) {
case 3: return 768; case 3: return 768;
...@@ -212,21 +213,22 @@ static inline unsigned get_rfs(struct i2s_dai *i2s) ...@@ -212,21 +213,22 @@ static inline unsigned get_rfs(struct i2s_dai *i2s)
static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)
{ {
u32 mod = readl(i2s->addr + I2SMOD); u32 mod = readl(i2s->addr + I2SMOD);
int rfs_shift = MOD_RCLK_SHIFT;
mod &= ~MOD_RCLK_MASK; mod &= ~(MOD_RCLK_MASK << rfs_shift);
switch (rfs) { switch (rfs) {
case 768: case 768:
mod |= MOD_RCLK_768FS; mod |= (MOD_RCLK_768FS << rfs_shift);
break; break;
case 512: case 512:
mod |= MOD_RCLK_512FS; mod |= (MOD_RCLK_512FS << rfs_shift);
break; break;
case 384: case 384:
mod |= MOD_RCLK_384FS; mod |= (MOD_RCLK_384FS << rfs_shift);
break; break;
default: default:
mod |= MOD_RCLK_256FS; mod |= (MOD_RCLK_256FS << rfs_shift);
break; break;
} }
...@@ -236,7 +238,8 @@ static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) ...@@ -236,7 +238,8 @@ static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)
/* Read Bit-Clock of I2S (in multiples of LRCLK) */ /* Read Bit-Clock of I2S (in multiples of LRCLK) */
static inline unsigned get_bfs(struct i2s_dai *i2s) static inline unsigned get_bfs(struct i2s_dai *i2s)
{ {
u32 bfs = (readl(i2s->addr + I2SMOD) >> 1) & 0x3; u32 bfs = readl(i2s->addr + I2SMOD) >> MOD_BCLK_SHIFT;
bfs &= MOD_BCLK_MASK;
switch (bfs) { switch (bfs) {
case 3: return 24; case 3: return 24;
...@@ -250,21 +253,22 @@ static inline unsigned get_bfs(struct i2s_dai *i2s) ...@@ -250,21 +253,22 @@ static inline unsigned get_bfs(struct i2s_dai *i2s)
static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs)
{ {
u32 mod = readl(i2s->addr + I2SMOD); u32 mod = readl(i2s->addr + I2SMOD);
int bfs_shift = MOD_BCLK_SHIFT;
mod &= ~MOD_BCLK_MASK; mod &= ~(MOD_BCLK_MASK << bfs_shift);
switch (bfs) { switch (bfs) {
case 48: case 48:
mod |= MOD_BCLK_48FS; mod |= (MOD_BCLK_48FS << bfs_shift);
break; break;
case 32: case 32:
mod |= MOD_BCLK_32FS; mod |= (MOD_BCLK_32FS << bfs_shift);
break; break;
case 24: case 24:
mod |= MOD_BCLK_24FS; mod |= (MOD_BCLK_24FS << bfs_shift);
break; break;
case 16: case 16:
mod |= MOD_BCLK_16FS; mod |= (MOD_BCLK_16FS << bfs_shift);
break; break;
default: default:
dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n"); dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n");
...@@ -491,20 +495,25 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, ...@@ -491,20 +495,25 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
{ {
struct i2s_dai *i2s = to_info(dai); struct i2s_dai *i2s = to_info(dai);
u32 mod = readl(i2s->addr + I2SMOD); u32 mod = readl(i2s->addr + I2SMOD);
int lrp_shift = MOD_LRP_SHIFT, sdf_shift = MOD_SDF_SHIFT;
int sdf_mask, lrp_rlow;
u32 tmp = 0; u32 tmp = 0;
sdf_mask = MOD_SDF_MASK << sdf_shift;
lrp_rlow = MOD_LR_RLOW << lrp_shift;
/* Format is priority */ /* Format is priority */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_RIGHT_J: case SND_SOC_DAIFMT_RIGHT_J:
tmp |= MOD_LR_RLOW; tmp |= lrp_rlow;
tmp |= MOD_SDF_MSB; tmp |= (MOD_SDF_MSB << sdf_shift);
break; break;
case SND_SOC_DAIFMT_LEFT_J: case SND_SOC_DAIFMT_LEFT_J:
tmp |= MOD_LR_RLOW; tmp |= lrp_rlow;
tmp |= MOD_SDF_LSB; tmp |= (MOD_SDF_LSB << sdf_shift);
break; break;
case SND_SOC_DAIFMT_I2S: case SND_SOC_DAIFMT_I2S:
tmp |= MOD_SDF_IIS; tmp |= (MOD_SDF_IIS << sdf_shift);
break; break;
default: default:
dev_err(&i2s->pdev->dev, "Format not supported\n"); dev_err(&i2s->pdev->dev, "Format not supported\n");
...@@ -519,10 +528,10 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, ...@@ -519,10 +528,10 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
case SND_SOC_DAIFMT_NB_NF: case SND_SOC_DAIFMT_NB_NF:
break; break;
case SND_SOC_DAIFMT_NB_IF: case SND_SOC_DAIFMT_NB_IF:
if (tmp & MOD_LR_RLOW) if (tmp & lrp_rlow)
tmp &= ~MOD_LR_RLOW; tmp &= ~lrp_rlow;
else else
tmp |= MOD_LR_RLOW; tmp |= lrp_rlow;
break; break;
default: default:
dev_err(&i2s->pdev->dev, "Polarity not supported\n"); dev_err(&i2s->pdev->dev, "Polarity not supported\n");
...@@ -544,15 +553,18 @@ static int i2s_set_fmt(struct snd_soc_dai *dai, ...@@ -544,15 +553,18 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
return -EINVAL; return -EINVAL;
} }
/*
* Don't change the I2S mode if any controller is active on this
* channel.
*/
if (any_active(i2s) && if (any_active(i2s) &&
((mod & (MOD_SDF_MASK | MOD_LR_RLOW ((mod & (sdf_mask | lrp_rlow | MOD_SLAVE)) != tmp)) {
| MOD_SLAVE)) != tmp)) {
dev_err(&i2s->pdev->dev, dev_err(&i2s->pdev->dev,
"%s:%d Other DAI busy\n", __func__, __LINE__); "%s:%d Other DAI busy\n", __func__, __LINE__);
return -EAGAIN; return -EAGAIN;
} }
mod &= ~(MOD_SDF_MASK | MOD_LR_RLOW | MOD_SLAVE); mod &= ~(sdf_mask | lrp_rlow | MOD_SLAVE);
mod |= tmp; mod |= tmp;
writel(mod, i2s->addr + I2SMOD); writel(mod, i2s->addr + I2SMOD);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment