Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
68637849
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
68637849
编写于
12月 02, 2012
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/kirkwood' into asoc-next
上级
81e2c0da
1703470a
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
168 addition
and
94 deletion
+168
-94
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-dma.c
+10
-6
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/kirkwood/kirkwood-i2s.c
+149
-86
sound/soc/kirkwood/kirkwood.h
sound/soc/kirkwood/kirkwood.h
+9
-2
未找到文件。
sound/soc/kirkwood/kirkwood-dma.c
浏览文件 @
68637849
...
...
@@ -22,12 +22,16 @@
#include "kirkwood.h"
#define KIRKWOOD_RATES \
(SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
(SNDRV_PCM_RATE_8000_192000 | \
SNDRV_PCM_RATE_CONTINUOUS | \
SNDRV_PCM_RATE_KNOT)
#define KIRKWOOD_FORMATS \
(SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
SNDRV_PCM_FMTBIT_S32_LE | \
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
struct
kirkwood_dma_priv
{
struct
snd_pcm_substream
*
play_stream
;
...
...
@@ -43,10 +47,10 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
SNDRV_PCM_INFO_PAUSE
),
.
formats
=
KIRKWOOD_FORMATS
,
.
rates
=
KIRKWOOD_RATES
,
.
rate_min
=
441
00
,
.
rate_max
=
96
000
,
.
rate_min
=
80
00
,
.
rate_max
=
384
000
,
.
channels_min
=
1
,
.
channels_max
=
2
,
.
channels_max
=
8
,
.
buffer_bytes_max
=
KIRKWOOD_SND_MAX_PERIOD_BYTES
*
KIRKWOOD_SND_MAX_PERIODS
,
.
period_bytes_min
=
KIRKWOOD_SND_MIN_PERIOD_BYTES
,
.
period_bytes_max
=
KIRKWOOD_SND_MAX_PERIOD_BYTES
,
...
...
sound/soc/kirkwood/kirkwood-i2s.c
浏览文件 @
68637849
...
...
@@ -99,6 +99,29 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
}
while
(
value
==
0
);
}
static
void
kirkwood_set_rate
(
struct
snd_soc_dai
*
dai
,
struct
kirkwood_dma_data
*
priv
,
unsigned
long
rate
)
{
uint32_t
clks_ctrl
;
if
(
rate
==
44100
||
rate
==
48000
||
rate
==
96000
)
{
/* use internal dco for supported rates */
dev_dbg
(
dai
->
dev
,
"%s: dco set rate = %lu
\n
"
,
__func__
,
rate
);
kirkwood_set_dco
(
priv
->
io
,
rate
);
clks_ctrl
=
KIRKWOOD_MCLK_SOURCE_DCO
;
}
else
if
(
!
IS_ERR
(
priv
->
extclk
))
{
/* use optional external clk for other rates */
dev_dbg
(
dai
->
dev
,
"%s: extclk set rate = %lu -> %lu
\n
"
,
__func__
,
rate
,
256
*
rate
);
clk_set_rate
(
priv
->
extclk
,
256
*
rate
);
clks_ctrl
=
KIRKWOOD_MCLK_SOURCE_EXTCLK
;
}
writel
(
clks_ctrl
,
priv
->
io
+
KIRKWOOD_CLOCKS_CTRL
);
}
static
int
kirkwood_i2s_startup
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
{
...
...
@@ -113,26 +136,21 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_dai
*
dai
)
{
struct
kirkwood_dma_data
*
priv
=
snd_soc_dai_get_drvdata
(
dai
);
unsigned
int
i2s_reg
,
reg
;
unsigned
long
i2s_value
,
value
;
uint32_t
ctl_play
,
ctl_rec
;
unsigned
int
i2s_reg
;
unsigned
long
i2s_value
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
i2s_reg
=
KIRKWOOD_I2S_PLAYCTL
;
reg
=
KIRKWOOD_PLAYCTL
;
}
else
{
i2s_reg
=
KIRKWOOD_I2S_RECCTL
;
reg
=
KIRKWOOD_RECCTL
;
}
/* set dco conf */
kirkwood_set_dco
(
priv
->
io
,
params_rate
(
params
));
kirkwood_set_rate
(
dai
,
priv
,
params_rate
(
params
));
i2s_value
=
readl
(
priv
->
io
+
i2s_reg
);
i2s_value
&=
~
KIRKWOOD_I2S_CTL_SIZE_MASK
;
value
=
readl
(
priv
->
io
+
reg
);
value
&=
~
KIRKWOOD_PLAYCTL_SIZE_MASK
;
/*
* Size settings in play/rec i2s control regs and play/rec control
* regs must be the same.
...
...
@@ -140,38 +158,57 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
switch
(
params_format
(
params
))
{
case
SNDRV_PCM_FORMAT_S16_LE
:
i2s_value
|=
KIRKWOOD_I2S_CTL_SIZE_16
;
value
|=
KIRKWOOD_PLAYCTL_SIZE_16_C
;
ctl_play
=
KIRKWOOD_PLAYCTL_SIZE_16_C
|
KIRKWOOD_PLAYCTL_I2S_EN
;
ctl_rec
=
KIRKWOOD_RECCTL_SIZE_16_C
|
KIRKWOOD_RECCTL_I2S_EN
;
break
;
/*
* doesn't work... S20_3LE != kirkwood 20bit format ?
*
case SNDRV_PCM_FORMAT_S20_3LE:
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
value |= KIRKWOOD_PLAYCTL_SIZE_20;
ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
KIRKWOOD_PLAYCTL_I2S_EN;
ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
KIRKWOOD_RECCTL_I2S_EN;
break;
*/
case
SNDRV_PCM_FORMAT_S24_LE
:
i2s_value
|=
KIRKWOOD_I2S_CTL_SIZE_24
;
value
|=
KIRKWOOD_PLAYCTL_SIZE_24
;
ctl_play
=
KIRKWOOD_PLAYCTL_SIZE_24
|
KIRKWOOD_PLAYCTL_I2S_EN
;
ctl_rec
=
KIRKWOOD_RECCTL_SIZE_24
|
KIRKWOOD_RECCTL_I2S_EN
;
break
;
case
SNDRV_PCM_FORMAT_S32_LE
:
i2s_value
|=
KIRKWOOD_I2S_CTL_SIZE_32
;
value
|=
KIRKWOOD_PLAYCTL_SIZE_32
;
ctl_play
=
KIRKWOOD_PLAYCTL_SIZE_32
|
KIRKWOOD_PLAYCTL_I2S_EN
;
ctl_rec
=
KIRKWOOD_RECCTL_SIZE_32
|
KIRKWOOD_RECCTL_I2S_EN
;
break
;
default:
return
-
EINVAL
;
}
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
value
&=
~
KIRKWOOD_PLAYCTL_MONO_MASK
;
if
(
params_channels
(
params
)
==
1
)
value
|=
KIRKWOOD_PLAYCTL_MONO_BOTH
;
ctl_play
|=
KIRKWOOD_PLAYCTL_MONO_BOTH
;
else
value
|=
KIRKWOOD_PLAYCTL_MONO_OFF
;
ctl_play
|=
KIRKWOOD_PLAYCTL_MONO_OFF
;
priv
->
ctl_play
&=
~
(
KIRKWOOD_PLAYCTL_MONO_MASK
|
KIRKWOOD_PLAYCTL_I2S_EN
|
KIRKWOOD_PLAYCTL_SPDIF_EN
|
KIRKWOOD_PLAYCTL_SIZE_MASK
);
priv
->
ctl_play
|=
ctl_play
;
}
else
{
priv
->
ctl_rec
&=
~
KIRKWOOD_RECCTL_SIZE_MASK
;
priv
->
ctl_rec
|=
ctl_rec
;
}
writel
(
i2s_value
,
priv
->
io
+
i2s_reg
);
writel
(
value
,
priv
->
io
+
reg
);
return
0
;
}
...
...
@@ -205,20 +242,18 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
/* configure */
ctl
=
priv
->
ctl_play
;
value
=
ctl
&
~
(
KIRKWOOD_PLAYCTL_I2S_EN
|
KIRKWOOD_PLAYCTL_SPDIF_EN
);
writel
(
value
,
priv
->
io
+
KIRKWOOD_PLAYCTL
);
/* enable interrupts */
value
=
readl
(
priv
->
io
+
KIRKWOOD_INT_MASK
);
value
|=
KIRKWOOD_INT_CAUSE_PLAY_BYTES
;
writel
(
value
,
priv
->
io
+
KIRKWOOD_INT_MASK
);
/* configure audio & enable i2s playback */
ctl
&=
~
KIRKWOOD_PLAYCTL_BURST_MASK
;
ctl
&=
~
(
KIRKWOOD_PLAYCTL_PAUSE
|
KIRKWOOD_PLAYCTL_I2S_MUTE
|
KIRKWOOD_PLAYCTL_SPDIF_EN
);
if
(
priv
->
burst
==
32
)
ctl
|=
KIRKWOOD_PLAYCTL_BURST_32
;
else
ctl
|=
KIRKWOOD_PLAYCTL_BURST_128
;
ctl
|=
KIRKWOOD_PLAYCTL_I2S_EN
;
/* enable playback */
writel
(
ctl
,
priv
->
io
+
KIRKWOOD_PLAYCTL
);
break
;
...
...
@@ -259,30 +294,24 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
int
cmd
,
struct
snd_soc_dai
*
dai
)
{
struct
kirkwood_dma_data
*
priv
=
snd_soc_dai_get_drvdata
(
dai
);
u
nsigned
long
value
;
u
int32_t
ctl
,
value
;
value
=
readl
(
priv
->
io
+
KIRKWOOD_RECCTL
);
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
/* configure */
ctl
=
priv
->
ctl_rec
;
value
=
ctl
&
~
KIRKWOOD_RECCTL_I2S_EN
;
writel
(
value
,
priv
->
io
+
KIRKWOOD_RECCTL
);
/* enable interrupts */
value
=
readl
(
priv
->
io
+
KIRKWOOD_INT_MASK
);
value
|=
KIRKWOOD_INT_CAUSE_REC_BYTES
;
writel
(
value
,
priv
->
io
+
KIRKWOOD_INT_MASK
);
/* configure audio & enable i2s record */
value
=
readl
(
priv
->
io
+
KIRKWOOD_RECCTL
);
value
&=
~
KIRKWOOD_RECCTL_BURST_MASK
;
value
&=
~
KIRKWOOD_RECCTL_MONO
;
value
&=
~
(
KIRKWOOD_RECCTL_PAUSE
|
KIRKWOOD_RECCTL_MUTE
|
KIRKWOOD_RECCTL_SPDIF_EN
);
if
(
priv
->
burst
==
32
)
value
|=
KIRKWOOD_RECCTL_BURST_32
;
else
value
|=
KIRKWOOD_RECCTL_BURST_128
;
value
|=
KIRKWOOD_RECCTL_I2S_EN
;
writel
(
value
,
priv
->
io
+
KIRKWOOD_RECCTL
);
/* enable record */
writel
(
ctl
,
priv
->
io
+
KIRKWOOD_RECCTL
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
...
...
@@ -389,90 +418,125 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai = {
.
channels_min
=
1
,
.
channels_max
=
2
,
.
rates
=
KIRKWOOD_I2S_RATES
,
.
formats
=
KIRKWOOD_I2S_FORMATS
,},
.
formats
=
KIRKWOOD_I2S_FORMATS
,
},
.
capture
=
{
.
channels_min
=
1
,
.
channels_max
=
2
,
.
rates
=
KIRKWOOD_I2S_RATES
,
.
formats
=
KIRKWOOD_I2S_FORMATS
,},
.
formats
=
KIRKWOOD_I2S_FORMATS
,
},
.
ops
=
&
kirkwood_i2s_dai_ops
,
};
static
struct
snd_soc_dai_driver
kirkwood_i2s_dai_extclk
=
{
.
probe
=
kirkwood_i2s_probe
,
.
remove
=
kirkwood_i2s_remove
,
.
playback
=
{
.
channels_min
=
1
,
.
channels_max
=
2
,
.
rates
=
SNDRV_PCM_RATE_8000_192000
|
SNDRV_PCM_RATE_CONTINUOUS
|
SNDRV_PCM_RATE_KNOT
,
.
formats
=
KIRKWOOD_I2S_FORMATS
,
},
.
capture
=
{
.
channels_min
=
1
,
.
channels_max
=
2
,
.
rates
=
SNDRV_PCM_RATE_8000_192000
|
SNDRV_PCM_RATE_CONTINUOUS
|
SNDRV_PCM_RATE_KNOT
,
.
formats
=
KIRKWOOD_I2S_FORMATS
,
},
.
ops
=
&
kirkwood_i2s_dai_ops
,
};
static
__devinit
int
kirkwood_i2s_dev_probe
(
struct
platform_device
*
pdev
)
{
struct
resource
*
mem
;
struct
kirkwood_asoc_platform_data
*
data
=
pdev
->
dev
.
platform_data
;
struct
kirkwood_asoc_platform_data
*
data
=
pdev
->
dev
.
platform_data
;
struct
snd_soc_dai_driver
*
soc_dai
=
&
kirkwood_i2s_dai
;
struct
kirkwood_dma_data
*
priv
;
struct
resource
*
mem
;
int
err
;
priv
=
kzalloc
(
sizeof
(
struct
kirkwood_dma_data
),
GFP_KERNEL
);
priv
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
*
priv
),
GFP_KERNEL
);
if
(
!
priv
)
{
dev_err
(
&
pdev
->
dev
,
"allocation failed
\n
"
);
err
=
-
ENOMEM
;
goto
error
;
return
-
ENOMEM
;
}
dev_set_drvdata
(
&
pdev
->
dev
,
priv
);
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
mem
)
{
dev_err
(
&
pdev
->
dev
,
"platform_get_resource failed
\n
"
);
err
=
-
ENXIO
;
goto
err_alloc
;
}
priv
->
mem
=
request_mem_region
(
mem
->
start
,
SZ_16K
,
DRV_NAME
);
if
(
!
priv
->
mem
)
{
dev_err
(
&
pdev
->
dev
,
"request_mem_region failed
\n
"
);
err
=
-
EBUSY
;
goto
err_alloc
;
return
-
ENXIO
;
}
priv
->
io
=
ioremap
(
priv
->
mem
->
start
,
SZ_16K
);
priv
->
io
=
devm_request_and_ioremap
(
&
pdev
->
dev
,
mem
);
if
(
!
priv
->
io
)
{
dev_err
(
&
pdev
->
dev
,
"ioremap failed
\n
"
);
err
=
-
ENOMEM
;
goto
err_iomem
;
dev_err
(
&
pdev
->
dev
,
"devm_request_and_ioremap failed
\n
"
);
return
-
ENOMEM
;
}
priv
->
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
priv
->
irq
<=
0
)
{
dev_err
(
&
pdev
->
dev
,
"platform_get_irq failed
\n
"
);
err
=
-
ENXIO
;
goto
err_ioremap
;
return
-
ENXIO
;
}
if
(
!
data
)
{
dev_err
(
&
pdev
->
dev
,
"no platform data ?!
\n
"
);
err
=
-
EINVAL
;
goto
err_ioremap
;
return
-
EINVAL
;
}
priv
->
burst
=
data
->
burst
;
priv
->
clk
=
clk_get
(
&
pdev
->
dev
,
NULL
);
priv
->
clk
=
devm_
clk_get
(
&
pdev
->
dev
,
NULL
);
if
(
IS_ERR
(
priv
->
clk
))
{
dev_err
(
&
pdev
->
dev
,
"no clock
\n
"
);
err
=
PTR_ERR
(
priv
->
clk
);
goto
err_ioremap
;
return
PTR_ERR
(
priv
->
clk
);
}
err
=
clk_prepare_enable
(
priv
->
clk
);
if
(
err
<
0
)
return
err
;
priv
->
extclk
=
clk_get
(
&
pdev
->
dev
,
"extclk"
);
if
(
!
IS_ERR
(
priv
->
extclk
))
{
if
(
priv
->
extclk
==
priv
->
clk
)
{
clk_put
(
priv
->
extclk
);
priv
->
extclk
=
ERR_PTR
(
-
EINVAL
);
}
else
{
dev_info
(
&
pdev
->
dev
,
"found external clock
\n
"
);
clk_prepare_enable
(
priv
->
extclk
);
soc_dai
=
&
kirkwood_i2s_dai_extclk
;
}
}
/* Some sensible defaults - this reflects the powerup values */
priv
->
ctl_play
=
KIRKWOOD_PLAYCTL_SIZE_24
;
priv
->
ctl_rec
=
KIRKWOOD_RECCTL_SIZE_24
;
/* Select the burst size */
if
(
data
->
burst
==
32
)
{
priv
->
ctl_play
|=
KIRKWOOD_PLAYCTL_BURST_32
;
priv
->
ctl_rec
|=
KIRKWOOD_RECCTL_BURST_32
;
}
else
{
priv
->
ctl_play
|=
KIRKWOOD_PLAYCTL_BURST_128
;
priv
->
ctl_rec
|=
KIRKWOOD_RECCTL_BURST_128
;
}
clk_prepare_enable
(
priv
->
clk
);
err
=
snd_soc_register_dai
(
&
pdev
->
dev
,
&
kirkwood_i2s
_dai
);
err
=
snd_soc_register_dai
(
&
pdev
->
dev
,
soc
_dai
);
if
(
!
err
)
return
0
;
dev_err
(
&
pdev
->
dev
,
"snd_soc_register_dai failed
\n
"
);
if
(
!
IS_ERR
(
priv
->
extclk
))
{
clk_disable_unprepare
(
priv
->
extclk
);
clk_put
(
priv
->
extclk
);
}
clk_disable_unprepare
(
priv
->
clk
);
clk_put
(
priv
->
clk
);
err_ioremap:
iounmap
(
priv
->
io
);
err_iomem:
release_mem_region
(
priv
->
mem
->
start
,
SZ_16K
);
err_alloc:
kfree
(
priv
);
error:
return
err
;
}
...
...
@@ -482,12 +546,11 @@ static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
snd_soc_unregister_dai
(
&
pdev
->
dev
);
if
(
!
IS_ERR
(
priv
->
extclk
))
{
clk_disable_unprepare
(
priv
->
extclk
);
clk_put
(
priv
->
extclk
);
}
clk_disable_unprepare
(
priv
->
clk
);
clk_put
(
priv
->
clk
);
iounmap
(
priv
->
io
);
release_mem_region
(
priv
->
mem
->
start
,
SZ_16K
);
kfree
(
priv
);
return
0
;
}
...
...
sound/soc/kirkwood/kirkwood.h
浏览文件 @
68637849
...
...
@@ -77,6 +77,11 @@
#define KIRKWOOD_DCO_SPCR_STATUS 0x120c
#define KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK (1<<16)
#define KIRKWOOD_CLOCKS_CTRL 0x1230
#define KIRKWOOD_MCLK_SOURCE_MASK (3<<0)
#define KIRKWOOD_MCLK_SOURCE_DCO (0<<0)
#define KIRKWOOD_MCLK_SOURCE_EXTCLK (3<<0)
#define KIRKWOOD_ERR_CAUSE 0x1300
#define KIRKWOOD_ERR_MASK 0x1304
...
...
@@ -119,11 +124,13 @@
#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000
struct
kirkwood_dma_data
{
struct
resource
*
mem
;
void
__iomem
*
io
;
struct
clk
*
clk
;
struct
clk
*
extclk
;
uint32_t
ctl_play
;
uint32_t
ctl_rec
;
int
irq
;
int
burst
;
struct
clk
*
clk
;
};
#endif
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录