|
|
|
@ -58,6 +58,12 @@ |
|
|
|
|
|
|
|
|
|
#define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12 |
|
|
|
|
#define JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 8 |
|
|
|
|
#define JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 24 |
|
|
|
|
#define JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 16 |
|
|
|
|
#define JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_MASK \ |
|
|
|
|
(0xf << JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
|
|
|
|
#define JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_MASK \ |
|
|
|
|
(0x1f << JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
|
|
|
|
|
|
|
|
|
#define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19) |
|
|
|
|
#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16) |
|
|
|
@ -79,6 +85,7 @@ |
|
|
|
|
#define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET 16 |
|
|
|
|
|
|
|
|
|
#define JZ_AIC_I2S_FMT_DISABLE_BIT_CLK BIT(12) |
|
|
|
|
#define JZ_AIC_I2S_FMT_DISABLE_BIT_ICLK BIT(13) |
|
|
|
|
#define JZ_AIC_I2S_FMT_ENABLE_SYS_CLK BIT(4) |
|
|
|
|
#define JZ_AIC_I2S_FMT_MSB BIT(0) |
|
|
|
|
|
|
|
|
@ -87,6 +94,13 @@ |
|
|
|
|
#define JZ_AIC_CLK_DIV_MASK 0xf |
|
|
|
|
#define I2SDIV_DV_SHIFT 8 |
|
|
|
|
#define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT) |
|
|
|
|
#define I2SDIV_IDV_SHIFT 8 |
|
|
|
|
#define I2SDIV_IDV_MASK (0xf << I2SDIV_IDV_SHIFT) |
|
|
|
|
|
|
|
|
|
enum jz47xx_i2s_version { |
|
|
|
|
JZ_I2S_JZ4740, |
|
|
|
|
JZ_I2S_JZ4780, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct jz4740_i2s { |
|
|
|
|
struct resource *mem; |
|
|
|
@ -98,6 +112,8 @@ struct jz4740_i2s { |
|
|
|
|
|
|
|
|
|
struct snd_dmaengine_dai_dma_data playback_dma_data; |
|
|
|
|
struct snd_dmaengine_dai_dma_data capture_dma_data; |
|
|
|
|
|
|
|
|
|
enum jz47xx_i2s_version version; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, |
|
|
|
@ -267,13 +283,22 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, |
|
|
|
|
ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO; |
|
|
|
|
else |
|
|
|
|
ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO; |
|
|
|
|
|
|
|
|
|
div_reg &= ~I2SDIV_DV_MASK; |
|
|
|
|
div_reg |= (div - 1) << I2SDIV_DV_SHIFT; |
|
|
|
|
} else { |
|
|
|
|
ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; |
|
|
|
|
ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; |
|
|
|
|
|
|
|
|
|
if (i2s->version >= JZ_I2S_JZ4780) { |
|
|
|
|
div_reg &= ~I2SDIV_IDV_MASK; |
|
|
|
|
div_reg |= (div - 1) << I2SDIV_IDV_SHIFT; |
|
|
|
|
} else { |
|
|
|
|
div_reg &= ~I2SDIV_DV_MASK; |
|
|
|
|
div_reg |= (div - 1) << I2SDIV_DV_SHIFT; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
div_reg &= ~I2SDIV_DV_MASK; |
|
|
|
|
div_reg |= (div - 1) << I2SDIV_DV_SHIFT; |
|
|
|
|
jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); |
|
|
|
|
jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div_reg); |
|
|
|
|
|
|
|
|
@ -369,11 +394,19 @@ static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) |
|
|
|
|
snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, |
|
|
|
|
&i2s->capture_dma_data); |
|
|
|
|
|
|
|
|
|
conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | |
|
|
|
|
(8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | |
|
|
|
|
JZ_AIC_CONF_OVERFLOW_PLAY_LAST | |
|
|
|
|
JZ_AIC_CONF_I2S | |
|
|
|
|
JZ_AIC_CONF_INTERNAL_CODEC; |
|
|
|
|
if (i2s->version >= JZ_I2S_JZ4780) { |
|
|
|
|
conf = (7 << JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | |
|
|
|
|
(8 << JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | |
|
|
|
|
JZ_AIC_CONF_OVERFLOW_PLAY_LAST | |
|
|
|
|
JZ_AIC_CONF_I2S | |
|
|
|
|
JZ_AIC_CONF_INTERNAL_CODEC; |
|
|
|
|
} else { |
|
|
|
|
conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | |
|
|
|
|
(8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | |
|
|
|
|
JZ_AIC_CONF_OVERFLOW_PLAY_LAST | |
|
|
|
|
JZ_AIC_CONF_I2S | |
|
|
|
|
JZ_AIC_CONF_INTERNAL_CODEC; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, JZ_AIC_CONF_RESET); |
|
|
|
|
jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); |
|
|
|
@ -422,13 +455,34 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = { |
|
|
|
|
.resume = jz4740_i2s_resume, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static struct snd_soc_dai_driver jz4780_i2s_dai = { |
|
|
|
|
.probe = jz4740_i2s_dai_probe, |
|
|
|
|
.remove = jz4740_i2s_dai_remove, |
|
|
|
|
.playback = { |
|
|
|
|
.channels_min = 1, |
|
|
|
|
.channels_max = 2, |
|
|
|
|
.rates = SNDRV_PCM_RATE_8000_48000, |
|
|
|
|
.formats = JZ4740_I2S_FMTS, |
|
|
|
|
}, |
|
|
|
|
.capture = { |
|
|
|
|
.channels_min = 2, |
|
|
|
|
.channels_max = 2, |
|
|
|
|
.rates = SNDRV_PCM_RATE_8000_48000, |
|
|
|
|
.formats = JZ4740_I2S_FMTS, |
|
|
|
|
}, |
|
|
|
|
.ops = &jz4740_i2s_dai_ops, |
|
|
|
|
.suspend = jz4740_i2s_suspend, |
|
|
|
|
.resume = jz4740_i2s_resume, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static const struct snd_soc_component_driver jz4740_i2s_component = { |
|
|
|
|
.name = "jz4740-i2s", |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_OF |
|
|
|
|
static const struct of_device_id jz4740_of_matches[] = { |
|
|
|
|
{ .compatible = "ingenic,jz4740-i2s" }, |
|
|
|
|
{ .compatible = "ingenic,jz4740-i2s", .data = (void *)JZ_I2S_JZ4740 }, |
|
|
|
|
{ .compatible = "ingenic,jz4780-i2s", .data = (void *)JZ_I2S_JZ4780 }, |
|
|
|
|
{ /* sentinel */ } |
|
|
|
|
}; |
|
|
|
|
#endif |
|
|
|
@ -438,11 +492,16 @@ static int jz4740_i2s_dev_probe(struct platform_device *pdev) |
|
|
|
|
struct jz4740_i2s *i2s; |
|
|
|
|
struct resource *mem; |
|
|
|
|
int ret; |
|
|
|
|
const struct of_device_id *match; |
|
|
|
|
|
|
|
|
|
i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); |
|
|
|
|
if (!i2s) |
|
|
|
|
return -ENOMEM; |
|
|
|
|
|
|
|
|
|
match = of_match_device(jz4740_of_matches, &pdev->dev); |
|
|
|
|
if (match) |
|
|
|
|
i2s->version = (enum jz47xx_i2s_version)match->data; |
|
|
|
|
|
|
|
|
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|
|
|
|
i2s->base = devm_ioremap_resource(&pdev->dev, mem); |
|
|
|
|
if (IS_ERR(i2s->base)) |
|
|
|
@ -460,8 +519,13 @@ static int jz4740_i2s_dev_probe(struct platform_device *pdev) |
|
|
|
|
|
|
|
|
|
platform_set_drvdata(pdev, i2s); |
|
|
|
|
|
|
|
|
|
ret = devm_snd_soc_register_component(&pdev->dev, |
|
|
|
|
&jz4740_i2s_component, &jz4740_i2s_dai, 1); |
|
|
|
|
if (i2s->version == JZ_I2S_JZ4780) |
|
|
|
|
ret = devm_snd_soc_register_component(&pdev->dev, |
|
|
|
|
&jz4740_i2s_component, &jz4780_i2s_dai, 1); |
|
|
|
|
else |
|
|
|
|
ret = devm_snd_soc_register_component(&pdev->dev, |
|
|
|
|
&jz4740_i2s_component, &jz4740_i2s_dai, 1); |
|
|
|
|
|
|
|
|
|
if (ret) |
|
|
|
|
return ret; |
|
|
|
|
|
|
|
|
|