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
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