mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
rk3288 spdif: spdif sound support
This commit is contained in:
parent
7cc13f3700
commit
c94512d406
|
|
@ -105,6 +105,18 @@ dai0 {
|
|||
|
||||
rockchip-hdmi-spdif {
|
||||
compatible = "rockchip-hdmi-spdif";
|
||||
dais {
|
||||
dai0 {
|
||||
audio-codec = <&codec_hdmi_spdif>;
|
||||
i2s-controller = <&spdif>;
|
||||
format = "spdif";
|
||||
//continuous-clock;
|
||||
//bitclock-inversion;
|
||||
//frame-inversion;
|
||||
//bitclock-master;
|
||||
//frame-master;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
rockchip-rt5631 {
|
||||
|
|
|
|||
3
include/uapi/sound/asound.h
Normal file → Executable file
3
include/uapi/sound/asound.h
Normal file → Executable file
|
|
@ -216,6 +216,9 @@ typedef int __bitwise snd_pcm_format_t;
|
|||
#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD, 1-byte samples DSD (x8) */
|
||||
#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */
|
||||
#define SNDRV_NON_LINEAR_PCM_FORMAT_AC3 ((__force snd_pcm_format_t) 50) /* AC3,NON Linear PCM,spdif */
|
||||
#define SNDRV_NON_LINEAR_PCM_FORMAT_EAC3 ((__force snd_pcm_format_t) 51) /* EAC3,NON Linear PCM,spdif*/
|
||||
#define SNDRV_NON_LINEAR_PCM_FORMAT_DTS_I ((__force snd_pcm_format_t) 52) /* DTS-I,NON Linear PCM,spdif*/
|
||||
#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U16_LE
|
||||
|
||||
#ifdef SNDRV_LITTLE_ENDIAN
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@
|
|||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
|
||||
#include "card_info.h"
|
||||
#include "rk_pcm.h"
|
||||
|
||||
|
||||
#if 0
|
||||
#define RK_SPDIF_DBG(x...) printk(KERN_INFO "rk_hdmi_spdif:"x)
|
||||
#else
|
||||
|
|
@ -69,6 +73,8 @@ static int rk_hw_params(struct snd_pcm_substream *substream,
|
|||
|
||||
RK_SPDIF_DBG("spdif:Entered %s\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
||||
/* set codec DAI configuration */
|
||||
ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt);
|
||||
if (ret < 0) {
|
||||
|
|
@ -144,6 +150,12 @@ static int rockchip_hdmi_spdif_audio_probe(struct platform_device *pdev)
|
|||
|
||||
card->dev = &pdev->dev;
|
||||
|
||||
ret = rockchip_of_get_sound_card_info(card);
|
||||
if (ret) {
|
||||
printk("%s() get sound card info failed:%d\n", __FUNCTION__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_soc_register_card(card);
|
||||
|
||||
if (ret)
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/rockchip/iomap.h>
|
||||
#include <linux/rockchip/grf.h>
|
||||
|
||||
#include <asm/dma.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
|
@ -50,25 +53,49 @@
|
|||
|
||||
|
||||
/* Registers */
|
||||
#define CFGR 0x00
|
||||
#define SDBLR 0x04
|
||||
#define DMACR 0x08
|
||||
#define INTCR 0x0C
|
||||
#define INTSR 0x10
|
||||
#define XFER 0x18
|
||||
#define SMPDR 0x20
|
||||
#define CFGR 0x00
|
||||
#define SDBLR 0x04
|
||||
#define DMACR 0x08
|
||||
#define INTCR 0x0C
|
||||
#define INTSR 0x10
|
||||
#define XFER 0x18
|
||||
#define SMPDR 0x20
|
||||
|
||||
#define DATA_OUTBUF 0x20
|
||||
|
||||
#define CFGR_MASK 0x0ffffff
|
||||
#define SPDIF_CHNSR00_ADDR 0xC0
|
||||
#define SPDIF_CHNSR01_ADDR 0xC4
|
||||
#define SPDIF_CHNSR02_ADDR 0xC8
|
||||
#define SPDIF_CHNSR03_ADDR 0xCC
|
||||
#define SPDIF_CHNSR04_ADDR 0xD0
|
||||
#define SPDIF_CHNSR05_ADDR 0xD4
|
||||
#define SPDIF_CHNSR06_ADDR 0xD8
|
||||
#define SPDIF_CHNSR07_ADDR 0xDC
|
||||
#define SPDIF_CHNSR08_ADDR 0xE0
|
||||
#define SPDIF_CHNSR09_ADDR 0xE4
|
||||
#define SPDIF_CHNSR10_ADDR 0xE8
|
||||
#define SPDIF_CHNSR11_ADDR 0xEC
|
||||
|
||||
#define SPDIF_BURSTINFO 0x100
|
||||
#define SPDIF_REPETTION 0x104
|
||||
|
||||
#define DATA_OUTBUF 0x20
|
||||
|
||||
#define SPDIF_CHANNEL_SEL_8CH ((0x2<<16)|(0x0<<0))
|
||||
#define SPDIF_CHANNEL_SEL_2CH ((0x2<<16)|(0x2<<0))
|
||||
|
||||
//BURSTINFO bit0:6 //AC-3:0x01, DTS-I -II -III:11,12,13
|
||||
#define BURSTINFO_DATA_TYPE_AC3 0x01
|
||||
#define BURSTINFO_DATA_TYPE_EAC3 0x15
|
||||
#define BURSTINFO_DATA_TYPE_DTS_I 0x0b
|
||||
|
||||
#define CFGR_MASK 0x0ffffff
|
||||
#define CFGR_VALID_DATA_16bit (00)
|
||||
#define CFGR_VALID_DATA_20bit (01)
|
||||
#define CFGR_VALID_DATA_24bit (10)
|
||||
#define CFGR_VALID_DATA_MASK (11)
|
||||
|
||||
#define CFGR_HALFWORD_TX_ENABLE (0x1 << 2)
|
||||
#define CFGR_HALFWORD_TX_DISABLE (0x0 << 2)
|
||||
#define CFGR_HALFWORD_TX_MASK (0x1 << 2)
|
||||
#define CFGR_HALFWORD_TX_ENABLE (0x1<<2)
|
||||
#define CFGR_HALFWORD_TX_DISABLE (0x0<<2)
|
||||
#define CFGR_HALFWORD_TX_MASK (0x1<<2)
|
||||
|
||||
#define CFGR_CLK_RATE_MASK (0xFF<<16)
|
||||
|
||||
|
|
@ -76,19 +103,41 @@
|
|||
#define CFGR_JUSTIFIED_LEFT (1<<3)
|
||||
#define CFGR_JUSTIFIED_MASK (1<<3)
|
||||
|
||||
#define XFER_TRAN_STOP (0)
|
||||
#define XFER_TRAN_START (1)
|
||||
#define XFER_MASK (1)
|
||||
//CSE:channel status enable
|
||||
//The bit should be set to 1 when the channel conveys non-linear PCM
|
||||
#define CFGR_CSE_DISABLE (0<<6)
|
||||
#define CFGR_CSE_ENABLE (1<<6)
|
||||
#define CFGR_CSE_MASK (1<<6)
|
||||
|
||||
#define DMACR_TRAN_DMA_DISABLE (0<<5)
|
||||
#define DMACR_TRAN_DMA_ENABLE (1<<5)
|
||||
#define DMACR_TRAN_DMA_CTL_MASK (1<<5)
|
||||
|
||||
#define CFGR_MCLK_CLR (1<<7)
|
||||
|
||||
//new
|
||||
#define CFGR_LINEAR_PCM (0<<8)
|
||||
#define CFGR_NON_LINEAR_PCM (1<<8)
|
||||
#define CFGR_LINEAR_MASK (1<<8)
|
||||
|
||||
//support 7.1 amplifier,new
|
||||
#define CFGR_PRE_CHANGE_ENALBLE (1<<9)
|
||||
#define CFGR_PRE_CHANGE_DISABLE (0<<9)
|
||||
#define CFGR_PRE_CHANGE_MASK (1<<9)
|
||||
|
||||
#define XFER_TRAN_STOP (0)
|
||||
#define XFER_TRAN_START (1)
|
||||
#define XFER_MASK (1)
|
||||
|
||||
#define DMACR_TRAN_DMA_DISABLE (0<<5)
|
||||
#define DMACR_TRAN_DMA_ENABLE (1<<5)
|
||||
#define DMACR_TRAN_DMA_CTL_MASK (1<<5)
|
||||
|
||||
#define DMACR_TRAN_DATA_LEVEL 0x10
|
||||
#define DMACR_TRAN_DATA_LEVEL_MASK 0x1F
|
||||
#define DMACR_TRAN_DMA_MASK 0x3F
|
||||
|
||||
#define DMACR_TRAN_DMA_MASK (0x3F)
|
||||
|
||||
//Sample Date Buffer empty interrupt enable,new
|
||||
#define INTCR_SDBEIE_DISABLE (0<<4)
|
||||
#define INTCR_SDBEIE_ENABLE (1<<4)
|
||||
#define INTCR_SDBEIE_MASK (1<<4)
|
||||
|
||||
|
||||
struct rockchip_spdif_info {
|
||||
|
|
@ -118,14 +167,16 @@ static void spdif_snd_txctrl(struct rockchip_spdif_info *spdif, int on)
|
|||
xfer |= XFER_TRAN_START;
|
||||
opr |= DMACR_TRAN_DMA_ENABLE;
|
||||
writel(xfer, regs + XFER);
|
||||
writel(opr|0x10, regs + DMACR);
|
||||
writel(opr, regs + DMACR);
|
||||
RK_SPDIF_DBG("on xfer=0x%x,opr=0x%x\n",readl(regs + XFER),readl(regs + DMACR));
|
||||
}else{
|
||||
xfer &= ~XFER_TRAN_START;
|
||||
opr &= ~DMACR_TRAN_DMA_ENABLE;
|
||||
writel(xfer, regs + XFER);
|
||||
writel(opr|0x10, regs + DMACR);
|
||||
}
|
||||
writel(opr, regs + DMACR);
|
||||
writel(1<<7, regs + CFGR);
|
||||
RK_SPDIF_DBG("off xfer=0x%x,opr=0x%x\n",readl(regs + XFER),readl(regs + DMACR));
|
||||
}
|
||||
}
|
||||
|
||||
static int spdif_set_syclk(struct snd_soc_dai *cpu_dai,
|
||||
|
|
@ -179,7 +230,8 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
|
|||
struct rockchip_spdif_info *spdif = to_info(dai);
|
||||
void __iomem *regs = spdif->regs;
|
||||
unsigned long flags;
|
||||
int cfgr, dmac;
|
||||
int cfgr, dmac,intcr,chnsr_byte[5]={0};
|
||||
int dataType,ErrFlag,DataLen,DataInfo,BsNum,Repetition,BurstInfo;
|
||||
|
||||
RK_SPDIF_DBG("Entered %s\n", __func__);
|
||||
|
||||
|
|
@ -212,18 +264,79 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
|
|||
cfgr &= ~CFGR_HALFWORD_TX_MASK;
|
||||
cfgr |= CFGR_HALFWORD_TX_ENABLE;
|
||||
|
||||
cfgr &= ~CFGR_CLK_RATE_MASK;
|
||||
cfgr &= ~CFGR_CLK_RATE_MASK;//set most MCLK:192kHz
|
||||
cfgr |= (1<<16);
|
||||
|
||||
cfgr &= ~CFGR_JUSTIFIED_MASK;
|
||||
cfgr |= CFGR_JUSTIFIED_RIGHT;
|
||||
|
||||
cfgr &= ~CFGR_CSE_MASK;
|
||||
cfgr |= CFGR_CSE_DISABLE;
|
||||
|
||||
cfgr &= ~CFGR_LINEAR_MASK;
|
||||
cfgr |= CFGR_LINEAR_PCM;
|
||||
if(!snd_pcm_format_linear(params_format(params))){//stream type
|
||||
cfgr |= CFGR_NON_LINEAR_PCM;
|
||||
}
|
||||
|
||||
cfgr &= ~CFGR_PRE_CHANGE_MASK;
|
||||
cfgr |= CFGR_PRE_CHANGE_ENALBLE;
|
||||
|
||||
writel(cfgr, regs + CFGR);
|
||||
|
||||
|
||||
intcr = readl(regs + INTCR) & INTCR_SDBEIE_MASK;
|
||||
intcr |= INTCR_SDBEIE_ENABLE;
|
||||
writel(intcr, regs + INTCR);
|
||||
|
||||
dmac = readl(regs + DMACR) & DMACR_TRAN_DMA_MASK & (~DMACR_TRAN_DATA_LEVEL_MASK);
|
||||
dmac |= 0x10;
|
||||
writel(dmac, regs + DMACR);
|
||||
|
||||
|
||||
/* channel byte 0:
|
||||
Bit 1 1 Main data field represents linear PCM samples.
|
||||
0 Main data field used for purposes other purposes.
|
||||
*/
|
||||
chnsr_byte[0]= (0x0)|(0x0<<1)|(0x0<<2)|(0x0<<3)|(0x00<<6);//consumer|pcm|copyright?|pre-emphasis|(0x00<<6);
|
||||
chnsr_byte[1]= (0x0);//category code general mode??
|
||||
chnsr_byte[2]= (0x0)|(0x0<<4)|(0x0<<6);//
|
||||
chnsr_byte[3]= (0x00)|(0x00);//khz;clock acurracy
|
||||
chnsr_byte[4]= (0x0<<4)|(0x01<<1|0x0);//16 bit;
|
||||
|
||||
if(!snd_pcm_format_linear(params_format(params))){//set stream type
|
||||
chnsr_byte[0] |= (0x1<<1);//set 0:represent main data is linear
|
||||
chnsr_byte[4] = (0x0<<4)|(0x00<<1|0x0);//16 bit;
|
||||
}
|
||||
writel((chnsr_byte[4]<<16)|(chnsr_byte[4]),regs+SPDIF_CHNSR02_ADDR);
|
||||
writel((chnsr_byte[3]<<24)|(chnsr_byte[2]<<16)|(chnsr_byte[3]<<8)|(chnsr_byte[2]),regs+SPDIF_CHNSR01_ADDR);
|
||||
writel((chnsr_byte[1]<<24)|(chnsr_byte[0]<<16)|(chnsr_byte[1]<<8)|(chnsr_byte[0]),regs+SPDIF_CHNSR00_ADDR);
|
||||
|
||||
if(!snd_pcm_format_linear(params_format(params))) {//set non-linear params
|
||||
switch(params_format(params)){
|
||||
case SNDRV_NON_LINEAR_PCM_FORMAT_AC3:
|
||||
//bit0:6 //AC-3:0x01, DTS-I -II -III:11,12,13
|
||||
dataType = BURSTINFO_DATA_TYPE_AC3;
|
||||
//Repetition:AC-3:1536 DTS-I -II -III:512,1024,2048 EAC3:6144
|
||||
Repetition = 1536;
|
||||
break;
|
||||
case SNDRV_NON_LINEAR_PCM_FORMAT_DTS_I:
|
||||
dataType = BURSTINFO_DATA_TYPE_DTS_I;
|
||||
Repetition = 512;
|
||||
break;
|
||||
case SNDRV_NON_LINEAR_PCM_FORMAT_EAC3:
|
||||
dataType = BURSTINFO_DATA_TYPE_EAC3;
|
||||
Repetition = 6144;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
ErrFlag=0x0;
|
||||
DataLen=params_period_size(params)*2*16;//bit32:16 //640kbps:0x5000 448kbps:0x3800
|
||||
DataInfo=0;
|
||||
BsNum=0x0;
|
||||
BurstInfo = (DataLen<<16)|(BsNum<<13)|(DataInfo<<8)|(ErrFlag<<7)|dataType;
|
||||
writel(BurstInfo,regs+SPDIF_BURSTINFO);
|
||||
writel(Repetition,regs+SPDIF_REPETTION);
|
||||
}
|
||||
spin_unlock_irqrestore(&spdif->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
|
@ -301,13 +414,15 @@ static int spdif_probe(struct platform_device *pdev)
|
|||
return -ENXIO;
|
||||
}
|
||||
|
||||
spdif->clk= clk_get(&pdev->dev, NULL);
|
||||
spdif->clk= clk_get(&pdev->dev, "spdif_mclk");
|
||||
if (IS_ERR(spdif->clk)) {
|
||||
dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
|
||||
return PTR_ERR(spdif->clk);
|
||||
}
|
||||
clk_prepare_enable(spdif->clk);
|
||||
clk_set_rate(spdif->clk, 12288000);//clk have some problem
|
||||
clk_set_rate(spdif->clk, 11289600);
|
||||
clk_prepare_enable(spdif->clk);
|
||||
|
||||
|
||||
/* Request S/PDIF Register's memory region */
|
||||
if (!request_mem_region(mem_res->start,
|
||||
|
|
@ -346,6 +461,7 @@ static int spdif_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, spdif);
|
||||
writel_relaxed(SPDIF_CHANNEL_SEL_8CH, RK_GRF_VIRT + RK3288_GRF_SOC_CON2);
|
||||
|
||||
RK_SPDIF_DBG("spdif:spdif probe ok!\n");
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user