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
75aac820
Commit
75aac820
authored
Jan 02, 2014
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/dma' into asoc-next
parents
01ad154e
2b67f8ba
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
144 additions
and
21 deletions
+144
-21
drivers/dma/dmaengine.c
drivers/dma/dmaengine.c
+31
-4
drivers/dma/of-dma.c
drivers/dma/of-dma.c
+9
-6
include/linux/dmaengine.h
include/linux/dmaengine.h
+8
-0
include/sound/dmaengine_pcm.h
include/sound/dmaengine_pcm.h
+10
-0
sound/soc/soc-devres.c
sound/soc/soc-devres.c
+41
-0
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-generic-dmaengine-pcm.c
+45
-11
No files found.
drivers/dma/dmaengine.c
View file @
75aac820
...
...
@@ -540,6 +540,8 @@ EXPORT_SYMBOL_GPL(dma_get_slave_channel);
* @mask: capabilities that the channel must satisfy
* @fn: optional callback to disposition available channels
* @fn_param: opaque parameter to pass to dma_filter_fn
*
* Returns pointer to appropriate DMA channel on success or NULL.
*/
struct
dma_chan
*
__dma_request_channel
(
const
dma_cap_mask_t
*
mask
,
dma_filter_fn
fn
,
void
*
fn_param
)
...
...
@@ -591,18 +593,43 @@ EXPORT_SYMBOL_GPL(__dma_request_channel);
* dma_request_slave_channel - try to allocate an exclusive slave channel
* @dev: pointer to client device structure
* @name: slave channel name
*
* Returns pointer to appropriate DMA channel on success or an error pointer.
*/
struct
dma_chan
*
dma_request_slave_channel
(
struct
device
*
dev
,
const
char
*
name
)
struct
dma_chan
*
dma_request_slave_channel_reason
(
struct
device
*
dev
,
const
char
*
name
)
{
struct
dma_chan
*
chan
;
/* If device-tree is present get slave info from here */
if
(
dev
->
of_node
)
return
of_dma_request_slave_channel
(
dev
->
of_node
,
name
);
/* If device was enumerated by ACPI get slave info from here */
if
(
ACPI_HANDLE
(
dev
))
return
acpi_dma_request_slave_chan_by_name
(
dev
,
name
);
if
(
ACPI_HANDLE
(
dev
))
{
chan
=
acpi_dma_request_slave_chan_by_name
(
dev
,
name
);
if
(
chan
)
return
chan
;
}
return
NULL
;
return
ERR_PTR
(
-
ENODEV
);
}
EXPORT_SYMBOL_GPL
(
dma_request_slave_channel_reason
);
/**
* dma_request_slave_channel - try to allocate an exclusive slave channel
* @dev: pointer to client device structure
* @name: slave channel name
*
* Returns pointer to appropriate DMA channel on success or NULL.
*/
struct
dma_chan
*
dma_request_slave_channel
(
struct
device
*
dev
,
const
char
*
name
)
{
struct
dma_chan
*
ch
=
dma_request_slave_channel_reason
(
dev
,
name
);
if
(
IS_ERR
(
ch
))
return
NULL
;
return
ch
;
}
EXPORT_SYMBOL_GPL
(
dma_request_slave_channel
);
...
...
drivers/dma/of-dma.c
View file @
75aac820
...
...
@@ -143,7 +143,7 @@ static int of_dma_match_channel(struct device_node *np, const char *name,
* @np: device node to get DMA request from
* @name: name of desired channel
*
* Returns pointer to appropriate
dma channel on success or NULL on erro
r.
* Returns pointer to appropriate
DMA channel on success or an error pointe
r.
*/
struct
dma_chan
*
of_dma_request_slave_channel
(
struct
device_node
*
np
,
const
char
*
name
)
...
...
@@ -152,17 +152,18 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
struct
of_dma
*
ofdma
;
struct
dma_chan
*
chan
;
int
count
,
i
;
int
ret_no_channel
=
-
ENODEV
;
if
(
!
np
||
!
name
)
{
pr_err
(
"%s: not enough information provided
\n
"
,
__func__
);
return
NULL
;
return
ERR_PTR
(
-
ENODEV
)
;
}
count
=
of_property_count_strings
(
np
,
"dma-names"
);
if
(
count
<
0
)
{
pr_err
(
"%s: dma-names property of node '%s' missing or empty
\n
"
,
__func__
,
np
->
full_name
);
return
NULL
;
return
ERR_PTR
(
-
ENODEV
)
;
}
for
(
i
=
0
;
i
<
count
;
i
++
)
{
...
...
@@ -172,10 +173,12 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
mutex_lock
(
&
of_dma_lock
);
ofdma
=
of_dma_find_controller
(
&
dma_spec
);
if
(
ofdma
)
if
(
ofdma
)
{
chan
=
ofdma
->
of_dma_xlate
(
&
dma_spec
,
ofdma
);
else
}
else
{
ret_no_channel
=
-
EPROBE_DEFER
;
chan
=
NULL
;
}
mutex_unlock
(
&
of_dma_lock
);
...
...
@@ -185,7 +188,7 @@ struct dma_chan *of_dma_request_slave_channel(struct device_node *np,
return
chan
;
}
return
NULL
;
return
ERR_PTR
(
ret_no_channel
)
;
}
/**
...
...
include/linux/dmaengine.h
View file @
75aac820
...
...
@@ -22,6 +22,7 @@
#define LINUX_DMAENGINE_H
#include <linux/device.h>
#include <linux/err.h>
#include <linux/uio.h>
#include <linux/bug.h>
#include <linux/scatterlist.h>
...
...
@@ -1040,6 +1041,8 @@ enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
void
dma_issue_pending_all
(
void
);
struct
dma_chan
*
__dma_request_channel
(
const
dma_cap_mask_t
*
mask
,
dma_filter_fn
fn
,
void
*
fn_param
);
struct
dma_chan
*
dma_request_slave_channel_reason
(
struct
device
*
dev
,
const
char
*
name
);
struct
dma_chan
*
dma_request_slave_channel
(
struct
device
*
dev
,
const
char
*
name
);
void
dma_release_channel
(
struct
dma_chan
*
chan
);
#else
...
...
@@ -1063,6 +1066,11 @@ static inline struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask,
{
return
NULL
;
}
static
inline
struct
dma_chan
*
dma_request_slave_channel_reason
(
struct
device
*
dev
,
const
char
*
name
)
{
return
ERR_PTR
(
-
ENODEV
);
}
static
inline
struct
dma_chan
*
dma_request_slave_channel
(
struct
device
*
dev
,
const
char
*
name
)
{
...
...
include/sound/dmaengine_pcm.h
View file @
75aac820
...
...
@@ -114,6 +114,10 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
* @compat_filter_fn: Will be used as the filter function when requesting a
* channel for platforms which do not use devicetree. The filter parameter
* will be the DAI's DMA data.
* @dma_dev: If set, request DMA channel on this device rather than the DAI
* device.
* @chan_names: If set, these custom DMA channel names will be requested at
* registration time.
* @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
* @prealloc_buffer_size: Size of the preallocated audio buffer.
*
...
...
@@ -130,6 +134,8 @@ struct snd_dmaengine_pcm_config {
struct
snd_soc_pcm_runtime
*
rtd
,
struct
snd_pcm_substream
*
substream
);
dma_filter_fn
compat_filter_fn
;
struct
device
*
dma_dev
;
const
char
*
chan_names
[
SNDRV_PCM_STREAM_LAST
+
1
];
const
struct
snd_pcm_hardware
*
pcm_hardware
;
unsigned
int
prealloc_buffer_size
;
...
...
@@ -140,6 +146,10 @@ int snd_dmaengine_pcm_register(struct device *dev,
unsigned
int
flags
);
void
snd_dmaengine_pcm_unregister
(
struct
device
*
dev
);
int
devm_snd_dmaengine_pcm_register
(
struct
device
*
dev
,
const
struct
snd_dmaengine_pcm_config
*
config
,
unsigned
int
flags
);
int
snd_dmaengine_pcm_prepare_slave_config
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
dma_slave_config
*
slave_config
);
...
...
sound/soc/soc-devres.c
View file @
75aac820
...
...
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
static
void
devm_component_release
(
struct
device
*
dev
,
void
*
res
)
{
...
...
@@ -84,3 +85,43 @@ int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
return
ret
;
}
EXPORT_SYMBOL_GPL
(
devm_snd_soc_register_card
);
#ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM
static
void
devm_dmaengine_pcm_release
(
struct
device
*
dev
,
void
*
res
)
{
snd_dmaengine_pcm_unregister
(
*
(
struct
device
**
)
res
);
}
/**
* devm_snd_dmaengine_pcm_register - resource managed dmaengine PCM registration
* @dev: The parent device for the PCM device
* @config: Platform specific PCM configuration
* @flags: Platform specific quirks
*
* Register a dmaengine based PCM device with automatic unregistration when the
* device is unregistered.
*/
int
devm_snd_dmaengine_pcm_register
(
struct
device
*
dev
,
const
struct
snd_dmaengine_pcm_config
*
config
,
unsigned
int
flags
)
{
struct
device
**
ptr
;
int
ret
;
ptr
=
devres_alloc
(
devm_dmaengine_pcm_release
,
sizeof
(
*
ptr
),
GFP_KERNEL
);
if
(
!
ptr
)
return
-
ENOMEM
;
ret
=
snd_dmaengine_pcm_register
(
dev
,
config
,
flags
);
if
(
ret
==
0
)
{
*
ptr
=
dev
;
devres_add
(
dev
,
ptr
);
}
else
{
devres_free
(
ptr
);
}
return
ret
;
}
EXPORT_SYMBOL_GPL
(
devm_snd_dmaengine_pcm_register
);
#endif
sound/soc/soc-generic-dmaengine-pcm.c
View file @
75aac820
...
...
@@ -137,6 +137,9 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
hw
.
buffer_bytes_max
=
SIZE_MAX
;
hw
.
fifo_size
=
dma_data
->
fifo_size
;
if
(
pcm
->
flags
&
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
)
hw
.
info
|=
SNDRV_PCM_INFO_BATCH
;
ret
=
dma_get_slave_caps
(
chan
,
&
dma_caps
);
if
(
ret
==
0
)
{
if
(
dma_caps
.
cmd_pause
)
...
...
@@ -284,25 +287,54 @@ static const char * const dmaengine_pcm_dma_channel_names[] = {
[
SNDRV_PCM_STREAM_CAPTURE
]
=
"rx"
,
};
static
void
dmaengine_pcm_request_chan_of
(
struct
dmaengine_pcm
*
pcm
,
struct
device
*
dev
)
static
int
dmaengine_pcm_request_chan_of
(
struct
dmaengine_pcm
*
pcm
,
struct
device
*
dev
,
const
struct
snd_dmaengine_pcm_config
*
config
)
{
unsigned
int
i
;
const
char
*
name
;
struct
dma_chan
*
chan
;
if
((
pcm
->
flags
&
(
SND_DMAENGINE_PCM_FLAG_NO_DT
|
SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME
))
||
!
dev
->
of_node
)
return
;
return
0
;
if
(
config
&&
config
->
dma_dev
)
{
/*
* If this warning is seen, it probably means that your Linux
* device structure does not match your HW device structure.
* It would be best to refactor the Linux device structure to
* correctly match the HW structure.
*/
dev_warn
(
dev
,
"DMA channels sourced from device %s"
,
dev_name
(
config
->
dma_dev
));
dev
=
config
->
dma_dev
;
}
if
(
pcm
->
flags
&
SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
{
pcm
->
chan
[
0
]
=
dma_request_slave_channel
(
dev
,
"rx-tx"
);
pcm
->
chan
[
1
]
=
pcm
->
chan
[
0
];
}
else
{
for
(
i
=
SNDRV_PCM_STREAM_PLAYBACK
;
i
<=
SNDRV_PCM_STREAM_CAPTURE
;
i
++
)
{
pcm
->
chan
[
i
]
=
dma_request_slave_channel
(
dev
,
dmaengine_pcm_dma_channel_names
[
i
]);
for
(
i
=
SNDRV_PCM_STREAM_PLAYBACK
;
i
<=
SNDRV_PCM_STREAM_CAPTURE
;
i
++
)
{
if
(
pcm
->
flags
&
SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
name
=
"rx-tx"
;
else
name
=
dmaengine_pcm_dma_channel_names
[
i
];
if
(
config
&&
config
->
chan_names
[
i
])
name
=
config
->
chan_names
[
i
];
chan
=
dma_request_slave_channel_reason
(
dev
,
name
);
if
(
IS_ERR
(
chan
))
{
if
(
PTR_ERR
(
chan
)
==
-
EPROBE_DEFER
)
return
-
EPROBE_DEFER
;
pcm
->
chan
[
i
]
=
NULL
;
}
else
{
pcm
->
chan
[
i
]
=
chan
;
}
if
(
pcm
->
flags
&
SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
break
;
}
if
(
pcm
->
flags
&
SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
pcm
->
chan
[
1
]
=
pcm
->
chan
[
0
];
return
0
;
}
static
void
dmaengine_pcm_release_chan
(
struct
dmaengine_pcm
*
pcm
)
...
...
@@ -338,7 +370,9 @@ int snd_dmaengine_pcm_register(struct device *dev,
pcm
->
config
=
config
;
pcm
->
flags
=
flags
;
dmaengine_pcm_request_chan_of
(
pcm
,
dev
);
ret
=
dmaengine_pcm_request_chan_of
(
pcm
,
dev
,
config
);
if
(
ret
)
goto
err_free_dma
;
if
(
flags
&
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
)
ret
=
snd_soc_add_platform
(
dev
,
&
pcm
->
platform
,
...
...
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