Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
e449f7a3
Commit
e449f7a3
authored
May 13, 2016
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branches 'asoc/topic/davinci' and 'asoc/topic/dwc' into asoc-next
parents
1c21e634
ddecd149
3fafd14d
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
183 additions
and
63 deletions
+183
-63
Documentation/devicetree/bindings/sound/davinci-mcbsp.txt
Documentation/devicetree/bindings/sound/davinci-mcbsp.txt
+51
-0
sound/soc/davinci/Kconfig
sound/soc/davinci/Kconfig
+5
-1
sound/soc/davinci/davinci-i2s.c
sound/soc/davinci/davinci-i2s.c
+54
-26
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.c
+58
-32
sound/soc/davinci/davinci-mcasp.h
sound/soc/davinci/davinci-mcasp.h
+5
-0
sound/soc/dwc/designware_i2s.c
sound/soc/dwc/designware_i2s.c
+10
-4
No files found.
Documentation/devicetree/bindings/sound/davinci-mcbsp.txt
0 → 100644
View file @
e449f7a3
Texas Instruments DaVinci McBSP module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This binding describes the "Multi-channel Buffered Serial Port" (McBSP)
audio interface found in some TI DaVinci processors like the OMAP-L138 or AM180x.
Required properties:
~~~~~~~~~~~~~~~~~~~~
- compatible :
"ti,da850-mcbsp" : for DA850, AM180x and OPAM-L138 platforms
- reg : physical base address and length of the controller memory mapped
region(s).
- reg-names : Should contain:
* "mpu" for the main registers (required).
* "dat" for the data FIFO (optional).
- dmas: three element list of DMA controller phandles, DMA request line and
TC channel ordered triplets.
- dma-names: identifier string for each DMA request line in the dmas property.
These strings correspond 1:1 with the ordered pairs in dmas. The dma
identifiers must be "rx" and "tx".
Optional properties:
~~~~~~~~~~~~~~~~~~~~
- interrupts : Interrupt numbers for McBSP
- interrupt-names : Known interrupt names are "rx" and "tx"
- pinctrl-0: Should specify pin control group used for this controller.
- pinctrl-names: Should contain only one value - "default", for more details
please refer to pinctrl-bindings.txt
Example (AM1808):
~~~~~~~~~~~~~~~~~
mcbsp0: mcbsp@1d10000 {
compatible = "ti,da850-mcbsp";
pinctrl-names = "default";
pinctrl-0 = <&mcbsp0_pins>;
reg = <0x00110000 0x1000>,
<0x00310000 0x1000>;
reg-names = "mpu", "dat";
interrupts = <97 98>;
interrupts-names = "rx", "tx";
dmas = <&edma0 3 1
&edma0 2 1>;
dma-names = "tx", "rx";
status = "okay";
};
sound/soc/davinci/Kconfig
View file @
e449f7a3
...
@@ -16,7 +16,11 @@ config SND_EDMA_SOC
...
@@ -16,7 +16,11 @@ config SND_EDMA_SOC
- DRA7xx family
- DRA7xx family
config SND_DAVINCI_SOC_I2S
config SND_DAVINCI_SOC_I2S
tristate
tristate "DaVinci Multichannel Buffered Serial Port (McBSP) support"
depends on SND_EDMA_SOC
help
Say Y or M here if you want to have support for McBSP IP found in
Texas Instruments DaVinci DA850 SoCs.
config SND_DAVINCI_SOC_MCASP
config SND_DAVINCI_SOC_MCASP
tristate "Multichannel Audio Serial Port (McASP) support"
tristate "Multichannel Audio Serial Port (McASP) support"
...
...
sound/soc/davinci/davinci-i2s.c
View file @
e449f7a3
...
@@ -4,9 +4,15 @@
...
@@ -4,9 +4,15 @@
* Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
* Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
* Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
* Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
*
*
* DT support (c) 2016 Petr Kulhavy, Barix AG <petr@barix.com>
* based on davinci-mcasp.c DT support
*
* This program is free software; you can redistribute it and/or modify
* 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
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
* published by the Free Software Foundation.
*
* TODO:
* on DA850 implement HW FIFOs instead of DMA into DXR and DRR registers
*/
*/
#include <linux/init.h>
#include <linux/init.h>
...
@@ -650,13 +656,24 @@ static const struct snd_soc_component_driver davinci_i2s_component = {
...
@@ -650,13 +656,24 @@ static const struct snd_soc_component_driver davinci_i2s_component = {
static
int
davinci_i2s_probe
(
struct
platform_device
*
pdev
)
static
int
davinci_i2s_probe
(
struct
platform_device
*
pdev
)
{
{
struct
snd_dmaengine_dai_dma_data
*
dma_data
;
struct
davinci_mcbsp_dev
*
dev
;
struct
davinci_mcbsp_dev
*
dev
;
struct
resource
*
mem
,
*
res
;
struct
resource
*
mem
,
*
res
;
void
__iomem
*
io_base
;
void
__iomem
*
io_base
;
int
*
dma
;
int
*
dma
;
int
ret
;
int
ret
;
mem
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"mpu"
);
if
(
!
mem
)
{
dev_warn
(
&
pdev
->
dev
,
"
\"
mpu
\"
mem resource not found, using index 0
\n
"
);
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
mem
)
{
dev_err
(
&
pdev
->
dev
,
"no mem resource?
\n
"
);
return
-
ENODEV
;
}
}
io_base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
mem
);
io_base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
mem
);
if
(
IS_ERR
(
io_base
))
if
(
IS_ERR
(
io_base
))
return
PTR_ERR
(
io_base
);
return
PTR_ERR
(
io_base
);
...
@@ -666,39 +683,43 @@ static int davinci_i2s_probe(struct platform_device *pdev)
...
@@ -666,39 +683,43 @@ static int davinci_i2s_probe(struct platform_device *pdev)
if
(
!
dev
)
if
(
!
dev
)
return
-
ENOMEM
;
return
-
ENOMEM
;
dev
->
clk
=
clk_get
(
&
pdev
->
dev
,
NULL
);
if
(
IS_ERR
(
dev
->
clk
))
return
-
ENODEV
;
clk_enable
(
dev
->
clk
);
dev
->
base
=
io_base
;
dev
->
base
=
io_base
;
dev
->
dma_data
[
SNDRV_PCM_STREAM_PLAYBACK
].
addr
=
/* setup DMA, first TX, then RX */
(
dma_addr_t
)(
mem
->
start
+
DAVINCI_MCBSP_DXR_REG
);
dma_data
=
&
dev
->
dma_data
[
SNDRV_PCM_STREAM_PLAYBACK
];
dma_data
->
addr
=
(
dma_addr_t
)(
mem
->
start
+
DAVINCI_MCBSP_DXR_REG
);
dev
->
dma_data
[
SNDRV_PCM_STREAM_CAPTURE
].
addr
=
(
dma_addr_t
)(
mem
->
start
+
DAVINCI_MCBSP_DRR_REG
);
/* first TX, then RX */
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
0
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
0
);
if
(
!
res
)
{
if
(
res
)
{
dev_err
(
&
pdev
->
dev
,
"no DMA resource
\n
"
);
ret
=
-
ENXIO
;
goto
err_release_clk
;
}
dma
=
&
dev
->
dma_request
[
SNDRV_PCM_STREAM_PLAYBACK
];
dma
=
&
dev
->
dma_request
[
SNDRV_PCM_STREAM_PLAYBACK
];
*
dma
=
res
->
start
;
*
dma
=
res
->
start
;
dev
->
dma_data
[
SNDRV_PCM_STREAM_PLAYBACK
].
filter_data
=
dma
;
dma_data
->
filter_data
=
dma
;
}
else
if
(
IS_ENABLED
(
CONFIG_OF
)
&&
pdev
->
dev
.
of_node
)
{
dma_data
->
filter_data
=
"tx"
;
}
else
{
dev_err
(
&
pdev
->
dev
,
"Missing DMA tx resource
\n
"
);
return
-
ENODEV
;
}
dma_data
=
&
dev
->
dma_data
[
SNDRV_PCM_STREAM_CAPTURE
];
dma_data
->
addr
=
(
dma_addr_t
)(
mem
->
start
+
DAVINCI_MCBSP_DRR_REG
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
1
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
1
);
if
(
!
res
)
{
if
(
res
)
{
dev_err
(
&
pdev
->
dev
,
"no DMA resource
\n
"
);
ret
=
-
ENXIO
;
goto
err_release_clk
;
}
dma
=
&
dev
->
dma_request
[
SNDRV_PCM_STREAM_CAPTURE
];
dma
=
&
dev
->
dma_request
[
SNDRV_PCM_STREAM_CAPTURE
];
*
dma
=
res
->
start
;
*
dma
=
res
->
start
;
dev
->
dma_data
[
SNDRV_PCM_STREAM_CAPTURE
].
filter_data
=
dma
;
dma_data
->
filter_data
=
dma
;
}
else
if
(
IS_ENABLED
(
CONFIG_OF
)
&&
pdev
->
dev
.
of_node
)
{
dma_data
->
filter_data
=
"rx"
;
}
else
{
dev_err
(
&
pdev
->
dev
,
"Missing DMA rx resource
\n
"
);
return
-
ENODEV
;
}
dev
->
clk
=
clk_get
(
&
pdev
->
dev
,
NULL
);
if
(
IS_ERR
(
dev
->
clk
))
return
-
ENODEV
;
clk_enable
(
dev
->
clk
);
dev
->
dev
=
&
pdev
->
dev
;
dev
->
dev
=
&
pdev
->
dev
;
dev_set_drvdata
(
&
pdev
->
dev
,
dev
);
dev_set_drvdata
(
&
pdev
->
dev
,
dev
);
...
@@ -737,11 +758,18 @@ static int davinci_i2s_remove(struct platform_device *pdev)
...
@@ -737,11 +758,18 @@ static int davinci_i2s_remove(struct platform_device *pdev)
return
0
;
return
0
;
}
}
static
const
struct
of_device_id
davinci_i2s_match
[]
=
{
{
.
compatible
=
"ti,da850-mcbsp"
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
davinci_i2s_match
);
static
struct
platform_driver
davinci_mcbsp_driver
=
{
static
struct
platform_driver
davinci_mcbsp_driver
=
{
.
probe
=
davinci_i2s_probe
,
.
probe
=
davinci_i2s_probe
,
.
remove
=
davinci_i2s_remove
,
.
remove
=
davinci_i2s_remove
,
.
driver
=
{
.
driver
=
{
.
name
=
"davinci-mcbsp"
,
.
name
=
"davinci-mcbsp"
,
.
of_match_table
=
of_match_ptr
(
davinci_i2s_match
),
},
},
};
};
...
...
sound/soc/davinci/davinci-mcasp.c
View file @
e449f7a3
...
@@ -540,21 +540,19 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
...
@@ -540,21 +540,19 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
return
ret
;
return
ret
;
}
}
static
int
__davinci_mcasp_set_clkdiv
(
struct
snd_soc_dai
*
dai
,
int
div_id
,
static
int
__davinci_mcasp_set_clkdiv
(
struct
davinci_mcasp
*
mcasp
,
int
div_id
,
int
div
,
bool
explicit
)
int
div
,
bool
explicit
)
{
{
struct
davinci_mcasp
*
mcasp
=
snd_soc_dai_get_drvdata
(
dai
);
pm_runtime_get_sync
(
mcasp
->
dev
);
pm_runtime_get_sync
(
mcasp
->
dev
);
switch
(
div_id
)
{
switch
(
div_id
)
{
case
0
:
/* MCLK divider */
case
MCASP_CLKDIV_AUXCLK
:
/* MCLK divider */
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_AHCLKXCTL_REG
,
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_AHCLKXCTL_REG
,
AHCLKXDIV
(
div
-
1
),
AHCLKXDIV_MASK
);
AHCLKXDIV
(
div
-
1
),
AHCLKXDIV_MASK
);
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_AHCLKRCTL_REG
,
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_AHCLKRCTL_REG
,
AHCLKRDIV
(
div
-
1
),
AHCLKRDIV_MASK
);
AHCLKRDIV
(
div
-
1
),
AHCLKRDIV_MASK
);
break
;
break
;
case
1
:
/* BCLK divider */
case
MCASP_CLKDIV_BCLK
:
/* BCLK divider */
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_ACLKXCTL_REG
,
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_ACLKXCTL_REG
,
ACLKXDIV
(
div
-
1
),
ACLKXDIV_MASK
);
ACLKXDIV
(
div
-
1
),
ACLKXDIV_MASK
);
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_ACLKRCTL_REG
,
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_ACLKRCTL_REG
,
...
@@ -563,7 +561,8 @@ static int __davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id,
...
@@ -563,7 +561,8 @@ static int __davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id,
mcasp
->
bclk_div
=
div
;
mcasp
->
bclk_div
=
div
;
break
;
break
;
case
2
:
/*
case
MCASP_CLKDIV_BCLK_FS_RATIO
:
/*
* BCLK/LRCLK ratio descries how many bit-clock cycles
* BCLK/LRCLK ratio descries how many bit-clock cycles
* fit into one frame. The clock ratio is given for a
* fit into one frame. The clock ratio is given for a
* full period of data (for I2S format both left and
* full period of data (for I2S format both left and
...
@@ -591,7 +590,9 @@ static int __davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id,
...
@@ -591,7 +590,9 @@ static int __davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id,
static
int
davinci_mcasp_set_clkdiv
(
struct
snd_soc_dai
*
dai
,
int
div_id
,
static
int
davinci_mcasp_set_clkdiv
(
struct
snd_soc_dai
*
dai
,
int
div_id
,
int
div
)
int
div
)
{
{
return
__davinci_mcasp_set_clkdiv
(
dai
,
div_id
,
div
,
1
);
struct
davinci_mcasp
*
mcasp
=
snd_soc_dai_get_drvdata
(
dai
);
return
__davinci_mcasp_set_clkdiv
(
mcasp
,
div_id
,
div
,
1
);
}
}
static
int
davinci_mcasp_set_sysclk
(
struct
snd_soc_dai
*
dai
,
int
clk_id
,
static
int
davinci_mcasp_set_sysclk
(
struct
snd_soc_dai
*
dai
,
int
clk_id
,
...
@@ -999,27 +1000,53 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
...
@@ -999,27 +1000,53 @@ static int mcasp_dit_hw_param(struct davinci_mcasp *mcasp,
}
}
static
int
davinci_mcasp_calc_clk_div
(
struct
davinci_mcasp
*
mcasp
,
static
int
davinci_mcasp_calc_clk_div
(
struct
davinci_mcasp
*
mcasp
,
unsigned
int
bclk_freq
,
unsigned
int
bclk_freq
,
bool
set
)
int
*
error_ppm
)
{
{
int
div
=
mcasp
->
sysclk_freq
/
bclk_freq
;
int
error_ppm
;
int
rem
=
mcasp
->
sysclk_freq
%
bclk_freq
;
unsigned
int
sysclk_freq
=
mcasp
->
sysclk_freq
;
u32
reg
=
mcasp_get_reg
(
mcasp
,
DAVINCI_MCASP_AHCLKXCTL_REG
);
int
div
=
sysclk_freq
/
bclk_freq
;
int
rem
=
sysclk_freq
%
bclk_freq
;
int
aux_div
=
1
;
if
(
div
>
(
ACLKXDIV_MASK
+
1
))
{
if
(
reg
&
AHCLKXE
)
{
aux_div
=
div
/
(
ACLKXDIV_MASK
+
1
);
if
(
div
%
(
ACLKXDIV_MASK
+
1
))
aux_div
++
;
sysclk_freq
/=
aux_div
;
div
=
sysclk_freq
/
bclk_freq
;
rem
=
sysclk_freq
%
bclk_freq
;
}
else
if
(
set
)
{
dev_warn
(
mcasp
->
dev
,
"Too fast reference clock (%u)
\n
"
,
sysclk_freq
);
}
}
if
(
rem
!=
0
)
{
if
(
rem
!=
0
)
{
if
(
div
==
0
||
if
(
div
==
0
||
((
mcasp
->
sysclk_freq
/
div
)
-
bclk_freq
)
>
((
sysclk_freq
/
div
)
-
bclk_freq
)
>
(
bclk_freq
-
(
mcasp
->
sysclk_freq
/
(
div
+
1
))))
{
(
bclk_freq
-
(
sysclk_freq
/
(
div
+
1
))))
{
div
++
;
div
++
;
rem
=
rem
-
bclk_freq
;
rem
=
rem
-
bclk_freq
;
}
}
}
}
error_ppm
=
(
div
*
1000000
+
(
int
)
div64_long
(
1000000LL
*
rem
,
(
int
)
bclk_freq
))
/
div
-
1000000
;
if
(
set
)
{
if
(
error_ppm
)
if
(
error_ppm
)
*
error_ppm
=
dev_info
(
mcasp
->
dev
,
"Sample-rate is off by %d PPM
\n
"
,
(
div
*
1000000
+
(
int
)
div64_long
(
1000000LL
*
rem
,
error_ppm
);
(
int
)
bclk_freq
))
/
div
-
1000000
;
__davinci_mcasp_set_clkdiv
(
mcasp
,
MCASP_CLKDIV_BCLK
,
div
,
0
);
if
(
reg
&
AHCLKXE
)
__davinci_mcasp_set_clkdiv
(
mcasp
,
MCASP_CLKDIV_AUXCLK
,
aux_div
,
0
);
}
return
div
;
return
error_ppm
;
}
}
static
int
davinci_mcasp_hw_params
(
struct
snd_pcm_substream
*
substream
,
static
int
davinci_mcasp_hw_params
(
struct
snd_pcm_substream
*
substream
,
...
@@ -1044,18 +1071,11 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
...
@@ -1044,18 +1071,11 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
int
slots
=
mcasp
->
tdm_slots
;
int
slots
=
mcasp
->
tdm_slots
;
int
rate
=
params_rate
(
params
);
int
rate
=
params_rate
(
params
);
int
sbits
=
params_width
(
params
);
int
sbits
=
params_width
(
params
);
int
ppm
,
div
;
if
(
mcasp
->
slot_width
)
if
(
mcasp
->
slot_width
)
sbits
=
mcasp
->
slot_width
;
sbits
=
mcasp
->
slot_width
;
div
=
davinci_mcasp_calc_clk_div
(
mcasp
,
rate
*
sbits
*
slots
,
davinci_mcasp_calc_clk_div
(
mcasp
,
rate
*
sbits
*
slots
,
true
);
&
ppm
);
if
(
ppm
)
dev_info
(
mcasp
->
dev
,
"Sample-rate is off by %d PPM
\n
"
,
ppm
);
__davinci_mcasp_set_clkdiv
(
cpu_dai
,
1
,
div
,
0
);
}
}
ret
=
mcasp_common_hw_param
(
mcasp
,
substream
->
stream
,
ret
=
mcasp_common_hw_param
(
mcasp
,
substream
->
stream
,
...
@@ -1166,7 +1186,8 @@ static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params,
...
@@ -1166,7 +1186,8 @@ static int davinci_mcasp_hw_rule_rate(struct snd_pcm_hw_params *params,
davinci_mcasp_dai_rates
[
i
];
davinci_mcasp_dai_rates
[
i
];
int
ppm
;
int
ppm
;
davinci_mcasp_calc_clk_div
(
rd
->
mcasp
,
bclk_freq
,
&
ppm
);
ppm
=
davinci_mcasp_calc_clk_div
(
rd
->
mcasp
,
bclk_freq
,
false
);
if
(
abs
(
ppm
)
<
DAVINCI_MAX_RATE_ERROR_PPM
)
{
if
(
abs
(
ppm
)
<
DAVINCI_MAX_RATE_ERROR_PPM
)
{
if
(
range
.
empty
)
{
if
(
range
.
empty
)
{
range
.
min
=
davinci_mcasp_dai_rates
[
i
];
range
.
min
=
davinci_mcasp_dai_rates
[
i
];
...
@@ -1205,8 +1226,9 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params,
...
@@ -1205,8 +1226,9 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params,
if
(
rd
->
mcasp
->
slot_width
)
if
(
rd
->
mcasp
->
slot_width
)
sbits
=
rd
->
mcasp
->
slot_width
;
sbits
=
rd
->
mcasp
->
slot_width
;
davinci_mcasp_calc_clk_div
(
rd
->
mcasp
,
sbits
*
slots
*
rate
,
ppm
=
davinci_mcasp_calc_clk_div
(
rd
->
mcasp
,
&
ppm
);
sbits
*
slots
*
rate
,
false
);
if
(
abs
(
ppm
)
<
DAVINCI_MAX_RATE_ERROR_PPM
)
{
if
(
abs
(
ppm
)
<
DAVINCI_MAX_RATE_ERROR_PPM
)
{
snd_mask_set
(
&
nfmt
,
i
);
snd_mask_set
(
&
nfmt
,
i
);
count
++
;
count
++
;
...
@@ -1230,11 +1252,15 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
...
@@ -1230,11 +1252,15 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
int
i
,
dir
;
int
i
,
dir
;
int
tdm_slots
=
mcasp
->
tdm_slots
;
int
tdm_slots
=
mcasp
->
tdm_slots
;
if
(
mcasp
->
tdm_mask
[
substream
->
stream
])
/* Do not allow more then one stream per direction */
tdm_slots
=
hweight32
(
mcasp
->
tdm_mask
[
substream
->
stream
]);
if
(
mcasp
->
substreams
[
substream
->
stream
])
return
-
EBUSY
;
mcasp
->
substreams
[
substream
->
stream
]
=
substream
;
mcasp
->
substreams
[
substream
->
stream
]
=
substream
;
if
(
mcasp
->
tdm_mask
[
substream
->
stream
])
tdm_slots
=
hweight32
(
mcasp
->
tdm_mask
[
substream
->
stream
]);
if
(
mcasp
->
op_mode
==
DAVINCI_MCASP_DIT_MODE
)
if
(
mcasp
->
op_mode
==
DAVINCI_MCASP_DIT_MODE
)
return
0
;
return
0
;
...
...
sound/soc/davinci/davinci-mcasp.h
View file @
e449f7a3
...
@@ -306,4 +306,9 @@
...
@@ -306,4 +306,9 @@
#define NUMEVT(x) (((x) & 0xFF) << 8)
#define NUMEVT(x) (((x) & 0xFF) << 8)
#define NUMDMA_MASK (0xFF)
#define NUMDMA_MASK (0xFF)
/* clock divider IDs */
#define MCASP_CLKDIV_AUXCLK 0
/* HCLK divider from AUXCLK */
#define MCASP_CLKDIV_BCLK 1
/* BCLK divider from HCLK */
#define MCASP_CLKDIV_BCLK_FS_RATIO 2
/* to set BCLK FS ration */
#endif
/* DAVINCI_MCASP_H */
#endif
/* DAVINCI_MCASP_H */
sound/soc/dwc/designware_i2s.c
View file @
e449f7a3
...
@@ -100,6 +100,7 @@ struct dw_i2s_dev {
...
@@ -100,6 +100,7 @@ struct dw_i2s_dev {
struct
device
*
dev
;
struct
device
*
dev
;
u32
ccr
;
u32
ccr
;
u32
xfer_resolution
;
u32
xfer_resolution
;
u32
fifo_th
;
/* data related to DMA transfers b/w i2s and DMAC */
/* data related to DMA transfers b/w i2s and DMAC */
union
dw_i2s_snd_dma_data
play_dma_data
;
union
dw_i2s_snd_dma_data
play_dma_data
;
...
@@ -147,17 +148,18 @@ static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream)
...
@@ -147,17 +148,18 @@ static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream)
static
void
i2s_start
(
struct
dw_i2s_dev
*
dev
,
static
void
i2s_start
(
struct
dw_i2s_dev
*
dev
,
struct
snd_pcm_substream
*
substream
)
struct
snd_pcm_substream
*
substream
)
{
{
struct
i2s_clk_config_data
*
config
=
&
dev
->
config
;
u32
i
,
irq
;
u32
i
,
irq
;
i2s_write_reg
(
dev
->
i2s_base
,
IER
,
1
);
i2s_write_reg
(
dev
->
i2s_base
,
IER
,
1
);
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
for
(
i
=
0
;
i
<
4
;
i
++
)
{
for
(
i
=
0
;
i
<
(
config
->
chan_nr
/
2
)
;
i
++
)
{
irq
=
i2s_read_reg
(
dev
->
i2s_base
,
IMR
(
i
));
irq
=
i2s_read_reg
(
dev
->
i2s_base
,
IMR
(
i
));
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
i
),
irq
&
~
0x30
);
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
i
),
irq
&
~
0x30
);
}
}
i2s_write_reg
(
dev
->
i2s_base
,
ITER
,
1
);
i2s_write_reg
(
dev
->
i2s_base
,
ITER
,
1
);
}
else
{
}
else
{
for
(
i
=
0
;
i
<
4
;
i
++
)
{
for
(
i
=
0
;
i
<
(
config
->
chan_nr
/
2
)
;
i
++
)
{
irq
=
i2s_read_reg
(
dev
->
i2s_base
,
IMR
(
i
));
irq
=
i2s_read_reg
(
dev
->
i2s_base
,
IMR
(
i
));
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
i
),
irq
&
~
0x03
);
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
i
),
irq
&
~
0x03
);
}
}
...
@@ -231,14 +233,16 @@ static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
...
@@ -231,14 +233,16 @@ static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
i2s_write_reg
(
dev
->
i2s_base
,
TCR
(
ch_reg
),
i2s_write_reg
(
dev
->
i2s_base
,
TCR
(
ch_reg
),
dev
->
xfer_resolution
);
dev
->
xfer_resolution
);
i2s_write_reg
(
dev
->
i2s_base
,
TFCR
(
ch_reg
),
0x02
);
i2s_write_reg
(
dev
->
i2s_base
,
TFCR
(
ch_reg
),
dev
->
fifo_th
-
1
);
irq
=
i2s_read_reg
(
dev
->
i2s_base
,
IMR
(
ch_reg
));
irq
=
i2s_read_reg
(
dev
->
i2s_base
,
IMR
(
ch_reg
));
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
ch_reg
),
irq
&
~
0x30
);
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
ch_reg
),
irq
&
~
0x30
);
i2s_write_reg
(
dev
->
i2s_base
,
TER
(
ch_reg
),
1
);
i2s_write_reg
(
dev
->
i2s_base
,
TER
(
ch_reg
),
1
);
}
else
{
}
else
{
i2s_write_reg
(
dev
->
i2s_base
,
RCR
(
ch_reg
),
i2s_write_reg
(
dev
->
i2s_base
,
RCR
(
ch_reg
),
dev
->
xfer_resolution
);
dev
->
xfer_resolution
);
i2s_write_reg
(
dev
->
i2s_base
,
RFCR
(
ch_reg
),
0x07
);
i2s_write_reg
(
dev
->
i2s_base
,
RFCR
(
ch_reg
),
dev
->
fifo_th
-
1
);
irq
=
i2s_read_reg
(
dev
->
i2s_base
,
IMR
(
ch_reg
));
irq
=
i2s_read_reg
(
dev
->
i2s_base
,
IMR
(
ch_reg
));
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
ch_reg
),
irq
&
~
0x03
);
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
ch_reg
),
irq
&
~
0x03
);
i2s_write_reg
(
dev
->
i2s_base
,
RER
(
ch_reg
),
1
);
i2s_write_reg
(
dev
->
i2s_base
,
RER
(
ch_reg
),
1
);
...
@@ -498,6 +502,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev,
...
@@ -498,6 +502,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev,
*/
*/
u32
comp1
=
i2s_read_reg
(
dev
->
i2s_base
,
dev
->
i2s_reg_comp1
);
u32
comp1
=
i2s_read_reg
(
dev
->
i2s_base
,
dev
->
i2s_reg_comp1
);
u32
comp2
=
i2s_read_reg
(
dev
->
i2s_base
,
dev
->
i2s_reg_comp2
);
u32
comp2
=
i2s_read_reg
(
dev
->
i2s_base
,
dev
->
i2s_reg_comp2
);
u32
fifo_depth
=
1
<<
(
1
+
COMP1_FIFO_DEPTH_GLOBAL
(
comp1
));
u32
idx
;
u32
idx
;
if
(
dev
->
capability
&
DWC_I2S_RECORD
&&
if
(
dev
->
capability
&
DWC_I2S_RECORD
&&
...
@@ -536,6 +541,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev,
...
@@ -536,6 +541,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev,
dev
->
capability
|=
DW_I2S_SLAVE
;
dev
->
capability
|=
DW_I2S_SLAVE
;
}
}
dev
->
fifo_th
=
fifo_depth
/
2
;
return
0
;
return
0
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment