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
nexedi
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
Hide 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
- DRA7xx family
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
tristate "Multichannel Audio Serial Port (McASP) support"
...
...
sound/soc/davinci/davinci-i2s.c
View file @
e449f7a3
...
...
@@ -4,9 +4,15 @@
* Author: Vladimir Barinov, <vbarinov@embeddedalley.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
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* TODO:
* on DA850 implement HW FIFOs instead of DMA into DXR and DRR registers
*/
#include <linux/init.h>
...
...
@@ -650,13 +656,24 @@ static const struct snd_soc_component_driver davinci_i2s_component = {
static
int
davinci_i2s_probe
(
struct
platform_device
*
pdev
)
{
struct
snd_dmaengine_dai_dma_data
*
dma_data
;
struct
davinci_mcbsp_dev
*
dev
;
struct
resource
*
mem
,
*
res
;
void
__iomem
*
io_base
;
int
*
dma
;
int
ret
;
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
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
);
if
(
!
mem
)
{
dev_err
(
&
pdev
->
dev
,
"no mem resource?
\n
"
);
return
-
ENODEV
;
}
}
io_base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
mem
);
if
(
IS_ERR
(
io_base
))
return
PTR_ERR
(
io_base
);
...
...
@@ -666,39 +683,43 @@ static int davinci_i2s_probe(struct platform_device *pdev)
if
(
!
dev
)
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
->
dma_data
[
SNDRV_PCM_STREAM_PLAYBACK
].
addr
=
(
dma_addr_t
)(
mem
->
start
+
DAVINCI_MCBSP_DXR_REG
);
/* setup DMA, first TX, then RX */
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
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"no DMA resource
\n
"
);
ret
=
-
ENXIO
;
goto
err_release_clk
;
if
(
res
)
{
dma
=
&
dev
->
dma_request
[
SNDRV_PCM_STREAM_PLAYBACK
];
*
dma
=
res
->
start
;
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
=
&
dev
->
dma_request
[
SNDRV_PCM_STREAM_PLAYBACK
];
*
dma
=
res
->
start
;
d
ev
->
dma_data
[
SNDRV_PCM_STREAM_PLAYBACK
].
filter_data
=
dma
;
dma_data
=
&
dev
->
dma_data
[
SNDRV_PCM_STREAM_CAPTURE
]
;
d
ma_data
->
addr
=
(
dma_addr_t
)(
mem
->
start
+
DAVINCI_MCBSP_DRR_REG
)
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
1
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"no DMA resource
\n
"
);
ret
=
-
ENXIO
;
goto
err_release_clk
;
if
(
res
)
{
dma
=
&
dev
->
dma_request
[
SNDRV_PCM_STREAM_CAPTURE
];
*
dma
=
res
->
start
;
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
;
}
dma
=
&
dev
->
dma_request
[
SNDRV_PCM_STREAM_CAPTURE
];
*
dma
=
res
->
start
;
dev
->
dma_data
[
SNDRV_PCM_STREAM_CAPTURE
].
filter_data
=
dma
;
dev
->
clk
=
clk_get
(
&
pdev
->
dev
,
NULL
);
if
(
IS_ERR
(
dev
->
clk
))
return
-
ENODEV
;
clk_enable
(
dev
->
clk
);
dev
->
dev
=
&
pdev
->
dev
;
dev_set_drvdata
(
&
pdev
->
dev
,
dev
);
...
...
@@ -737,11 +758,18 @@ static int davinci_i2s_remove(struct platform_device *pdev)
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
=
{
.
probe
=
davinci_i2s_probe
,
.
remove
=
davinci_i2s_remove
,
.
driver
=
{
.
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,
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
)
{
struct
davinci_mcasp
*
mcasp
=
snd_soc_dai_get_drvdata
(
dai
);
pm_runtime_get_sync
(
mcasp
->
dev
);
switch
(
div_id
)
{
case
0
:
/* MCLK divider */
case
MCASP_CLKDIV_AUXCLK
:
/* MCLK divider */
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_AHCLKXCTL_REG
,
AHCLKXDIV
(
div
-
1
),
AHCLKXDIV_MASK
);
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_AHCLKRCTL_REG
,
AHCLKRDIV
(
div
-
1
),
AHCLKRDIV_MASK
);
break
;
case
1
:
/* BCLK divider */
case
MCASP_CLKDIV_BCLK
:
/* BCLK divider */
mcasp_mod_bits
(
mcasp
,
DAVINCI_MCASP_ACLKXCTL_REG
,
ACLKXDIV
(
div
-
1
),
ACLKXDIV_MASK
);
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,
mcasp
->
bclk_div
=
div
;
break
;
case
2
:
/*
case
MCASP_CLKDIV_BCLK_FS_RATIO
:
/*
* BCLK/LRCLK ratio descries how many bit-clock cycles
* fit into one frame. The clock ratio is given for a
* 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,
static
int
davinci_mcasp_set_clkdiv
(
struct
snd_soc_dai
*
dai
,
int
div_id
,
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
,
...
...
@@ -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
,
unsigned
int
bclk_freq
,
int
*
error_ppm
)
unsigned
int
bclk_freq
,
bool
set
)
{
int
div
=
mcasp
->
sysclk_freq
/
bclk_freq
;
int
rem
=
mcasp
->
sysclk_freq
%
bclk_freq
;
int
error_ppm
;
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
(
div
==
0
||
((
mcasp
->
sysclk_freq
/
div
)
-
bclk_freq
)
>
(
bclk_freq
-
(
mcasp
->
sysclk_freq
/
(
div
+
1
))))
{
((
sysclk_freq
/
div
)
-
bclk_freq
)
>
(
bclk_freq
-
(
sysclk_freq
/
(
div
+
1
))))
{
div
++
;
rem
=
rem
-
bclk_freq
;
}
}
if
(
error_ppm
)
*
error_ppm
=
(
div
*
1000000
+
(
int
)
div64_long
(
1000000LL
*
rem
,
(
int
)
bclk_freq
))
/
div
-
1000000
;
error_ppm
=
(
div
*
1000000
+
(
int
)
div64_long
(
1000000LL
*
rem
,
(
int
)
bclk_freq
))
/
div
-
1000000
;
if
(
set
)
{
if
(
error_ppm
)
dev_info
(
mcasp
->
dev
,
"Sample-rate is off by %d PPM
\n
"
,
error_ppm
);
__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
,
...
...
@@ -1044,18 +1071,11 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
int
slots
=
mcasp
->
tdm_slots
;
int
rate
=
params_rate
(
params
);
int
sbits
=
params_width
(
params
);
int
ppm
,
div
;
if
(
mcasp
->
slot_width
)
sbits
=
mcasp
->
slot_width
;
div
=
davinci_mcasp_calc_clk_div
(
mcasp
,
rate
*
sbits
*
slots
,
&
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
);
davinci_mcasp_calc_clk_div
(
mcasp
,
rate
*
sbits
*
slots
,
true
);
}
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,
davinci_mcasp_dai_rates
[
i
];
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
(
range
.
empty
)
{
range
.
min
=
davinci_mcasp_dai_rates
[
i
];
...
...
@@ -1205,8 +1226,9 @@ static int davinci_mcasp_hw_rule_format(struct snd_pcm_hw_params *params,
if
(
rd
->
mcasp
->
slot_width
)
sbits
=
rd
->
mcasp
->
slot_width
;
davinci_mcasp_calc_clk_div
(
rd
->
mcasp
,
sbits
*
slots
*
rate
,
&
ppm
);
ppm
=
davinci_mcasp_calc_clk_div
(
rd
->
mcasp
,
sbits
*
slots
*
rate
,
false
);
if
(
abs
(
ppm
)
<
DAVINCI_MAX_RATE_ERROR_PPM
)
{
snd_mask_set
(
&
nfmt
,
i
);
count
++
;
...
...
@@ -1230,11 +1252,15 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
int
i
,
dir
;
int
tdm_slots
=
mcasp
->
tdm_slots
;
if
(
mcasp
->
tdm_mask
[
substream
->
stream
])
tdm_slots
=
hweight32
(
mcasp
->
tdm_mask
[
substream
->
stream
]);
/* Do not allow more then one stream per direction */
if
(
mcasp
->
substreams
[
substream
->
stream
])
return
-
EBUSY
;
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
)
return
0
;
...
...
sound/soc/davinci/davinci-mcasp.h
View file @
e449f7a3
...
...
@@ -306,4 +306,9 @@
#define NUMEVT(x) (((x) & 0xFF) << 8)
#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 */
sound/soc/dwc/designware_i2s.c
View file @
e449f7a3
...
...
@@ -100,6 +100,7 @@ struct dw_i2s_dev {
struct
device
*
dev
;
u32
ccr
;
u32
xfer_resolution
;
u32
fifo_th
;
/* data related to DMA transfers b/w i2s and DMAC */
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)
static
void
i2s_start
(
struct
dw_i2s_dev
*
dev
,
struct
snd_pcm_substream
*
substream
)
{
struct
i2s_clk_config_data
*
config
=
&
dev
->
config
;
u32
i
,
irq
;
i2s_write_reg
(
dev
->
i2s_base
,
IER
,
1
);
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
));
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
i
),
irq
&
~
0x30
);
}
i2s_write_reg
(
dev
->
i2s_base
,
ITER
,
1
);
}
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
));
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)
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
i2s_write_reg
(
dev
->
i2s_base
,
TCR
(
ch_reg
),
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
));
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
ch_reg
),
irq
&
~
0x30
);
i2s_write_reg
(
dev
->
i2s_base
,
TER
(
ch_reg
),
1
);
}
else
{
i2s_write_reg
(
dev
->
i2s_base
,
RCR
(
ch_reg
),
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
));
i2s_write_reg
(
dev
->
i2s_base
,
IMR
(
ch_reg
),
irq
&
~
0x03
);
i2s_write_reg
(
dev
->
i2s_base
,
RER
(
ch_reg
),
1
);
...
...
@@ -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
comp2
=
i2s_read_reg
(
dev
->
i2s_base
,
dev
->
i2s_reg_comp2
);
u32
fifo_depth
=
1
<<
(
1
+
COMP1_FIFO_DEPTH_GLOBAL
(
comp1
));
u32
idx
;
if
(
dev
->
capability
&
DWC_I2S_RECORD
&&
...
...
@@ -536,6 +541,7 @@ static int dw_configure_dai(struct dw_i2s_dev *dev,
dev
->
capability
|=
DW_I2S_SLAVE
;
}
dev
->
fifo_th
=
fifo_depth
/
2
;
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