2007-10-16 23:26:11 -07:00
|
|
|
/*
|
|
|
|
* Atmel SSC driver
|
|
|
|
*
|
|
|
|
* Copyright (C) 2007 Atmel Corporation
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/list.h>
|
|
|
|
#include <linux/clk.h>
|
|
|
|
#include <linux/err.h>
|
|
|
|
#include <linux/io.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/atmel-ssc.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 01:04:11 -07:00
|
|
|
#include <linux/slab.h>
|
2011-07-03 12:14:56 -07:00
|
|
|
#include <linux/module.h>
|
2007-10-16 23:26:11 -07:00
|
|
|
|
2012-11-06 20:41:41 -07:00
|
|
|
#include <linux/of.h>
|
2013-01-11 07:08:31 -07:00
|
|
|
#include <linux/pinctrl/consumer.h>
|
2012-11-06 20:41:41 -07:00
|
|
|
|
2007-10-16 23:26:11 -07:00
|
|
|
/* Serialize access to ssc_list and user count */
|
|
|
|
static DEFINE_SPINLOCK(user_lock);
|
|
|
|
static LIST_HEAD(ssc_list);
|
|
|
|
|
|
|
|
struct ssc_device *ssc_request(unsigned int ssc_num)
|
|
|
|
{
|
|
|
|
int ssc_valid = 0;
|
|
|
|
struct ssc_device *ssc;
|
|
|
|
|
|
|
|
spin_lock(&user_lock);
|
|
|
|
list_for_each_entry(ssc, &ssc_list, list) {
|
2012-11-06 20:41:41 -07:00
|
|
|
if (ssc->pdev->dev.of_node) {
|
|
|
|
if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc")
|
|
|
|
== ssc_num) {
|
|
|
|
ssc_valid = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if (ssc->pdev->id == ssc_num) {
|
2007-10-16 23:26:11 -07:00
|
|
|
ssc_valid = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ssc_valid) {
|
|
|
|
spin_unlock(&user_lock);
|
2009-02-04 16:12:17 -07:00
|
|
|
pr_err("ssc: ssc%d platform device is missing\n", ssc_num);
|
2007-10-16 23:26:11 -07:00
|
|
|
return ERR_PTR(-ENODEV);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ssc->user) {
|
|
|
|
spin_unlock(&user_lock);
|
|
|
|
dev_dbg(&ssc->pdev->dev, "module busy\n");
|
|
|
|
return ERR_PTR(-EBUSY);
|
|
|
|
}
|
|
|
|
ssc->user++;
|
|
|
|
spin_unlock(&user_lock);
|
|
|
|
|
2013-06-07 09:26:09 -07:00
|
|
|
clk_prepare_enable(ssc->clk);
|
2007-10-16 23:26:11 -07:00
|
|
|
|
|
|
|
return ssc;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(ssc_request);
|
|
|
|
|
|
|
|
void ssc_free(struct ssc_device *ssc)
|
|
|
|
{
|
2013-07-18 00:48:40 -07:00
|
|
|
bool disable_clk = true;
|
|
|
|
|
2007-10-16 23:26:11 -07:00
|
|
|
spin_lock(&user_lock);
|
2013-07-18 00:48:40 -07:00
|
|
|
if (ssc->user)
|
2007-10-16 23:26:11 -07:00
|
|
|
ssc->user--;
|
2013-07-18 00:48:40 -07:00
|
|
|
else {
|
|
|
|
disable_clk = false;
|
2007-10-16 23:26:11 -07:00
|
|
|
dev_dbg(&ssc->pdev->dev, "device already free\n");
|
|
|
|
}
|
|
|
|
spin_unlock(&user_lock);
|
2013-07-18 00:48:40 -07:00
|
|
|
|
|
|
|
if (disable_clk)
|
|
|
|
clk_disable_unprepare(ssc->clk);
|
2007-10-16 23:26:11 -07:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(ssc_free);
|
|
|
|
|
2012-11-05 22:57:51 -07:00
|
|
|
static struct atmel_ssc_platform_data at91rm9200_config = {
|
|
|
|
.use_dma = 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct atmel_ssc_platform_data at91sam9g45_config = {
|
|
|
|
.use_dma = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct platform_device_id atmel_ssc_devtypes[] = {
|
|
|
|
{
|
|
|
|
.name = "at91rm9200_ssc",
|
|
|
|
.driver_data = (unsigned long) &at91rm9200_config,
|
|
|
|
}, {
|
|
|
|
.name = "at91sam9g45_ssc",
|
|
|
|
.driver_data = (unsigned long) &at91sam9g45_config,
|
|
|
|
}, {
|
|
|
|
/* sentinel */
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-11-06 20:41:41 -07:00
|
|
|
#ifdef CONFIG_OF
|
|
|
|
static const struct of_device_id atmel_ssc_dt_ids[] = {
|
|
|
|
{
|
|
|
|
.compatible = "atmel,at91rm9200-ssc",
|
|
|
|
.data = &at91rm9200_config,
|
|
|
|
}, {
|
|
|
|
.compatible = "atmel,at91sam9g45-ssc",
|
|
|
|
.data = &at91sam9g45_config,
|
|
|
|
}, {
|
|
|
|
/* sentinel */
|
|
|
|
}
|
|
|
|
};
|
|
|
|
MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static inline const struct atmel_ssc_platform_data * __init
|
|
|
|
atmel_ssc_get_driver_data(struct platform_device *pdev)
|
|
|
|
{
|
|
|
|
if (pdev->dev.of_node) {
|
|
|
|
const struct of_device_id *match;
|
|
|
|
match = of_match_node(atmel_ssc_dt_ids, pdev->dev.of_node);
|
|
|
|
if (match == NULL)
|
|
|
|
return NULL;
|
|
|
|
return match->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (struct atmel_ssc_platform_data *)
|
|
|
|
platform_get_device_id(pdev)->driver_data;
|
|
|
|
}
|
|
|
|
|
2012-10-15 20:56:59 -07:00
|
|
|
static int ssc_probe(struct platform_device *pdev)
|
2007-10-16 23:26:11 -07:00
|
|
|
{
|
|
|
|
struct resource *regs;
|
|
|
|
struct ssc_device *ssc;
|
2012-11-06 20:41:41 -07:00
|
|
|
const struct atmel_ssc_platform_data *plat_dat;
|
2013-01-11 07:08:31 -07:00
|
|
|
struct pinctrl *pinctrl;
|
|
|
|
|
|
|
|
pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
|
|
|
|
if (IS_ERR(pinctrl)) {
|
|
|
|
dev_err(&pdev->dev, "Failed to request pinctrl\n");
|
|
|
|
return PTR_ERR(pinctrl);
|
|
|
|
}
|
2007-10-16 23:26:11 -07:00
|
|
|
|
2012-10-15 20:56:58 -07:00
|
|
|
ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
|
2007-10-16 23:26:11 -07:00
|
|
|
if (!ssc) {
|
|
|
|
dev_dbg(&pdev->dev, "out of memory\n");
|
2012-10-15 20:56:58 -07:00
|
|
|
return -ENOMEM;
|
2007-10-16 23:26:11 -07:00
|
|
|
}
|
|
|
|
|
2012-10-15 20:56:58 -07:00
|
|
|
ssc->pdev = pdev;
|
2012-11-06 20:41:41 -07:00
|
|
|
|
|
|
|
plat_dat = atmel_ssc_get_driver_data(pdev);
|
|
|
|
if (!plat_dat)
|
|
|
|
return -ENODEV;
|
|
|
|
ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat;
|
2012-10-15 20:56:58 -07:00
|
|
|
|
2007-10-16 23:26:11 -07:00
|
|
|
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
2013-01-21 03:09:10 -07:00
|
|
|
ssc->regs = devm_ioremap_resource(&pdev->dev, regs);
|
|
|
|
if (IS_ERR(ssc->regs))
|
|
|
|
return PTR_ERR(ssc->regs);
|
2012-10-15 20:56:58 -07:00
|
|
|
|
2012-11-20 01:38:17 -07:00
|
|
|
ssc->phybase = regs->start;
|
|
|
|
|
2012-10-15 20:56:58 -07:00
|
|
|
ssc->clk = devm_clk_get(&pdev->dev, "pclk");
|
|
|
|
if (IS_ERR(ssc->clk)) {
|
|
|
|
dev_dbg(&pdev->dev, "no pclk clock defined\n");
|
|
|
|
return -ENXIO;
|
2007-10-16 23:26:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* disable all interrupts */
|
2013-06-07 09:26:09 -07:00
|
|
|
clk_prepare_enable(ssc->clk);
|
2012-12-08 05:46:41 -07:00
|
|
|
ssc_writel(ssc->regs, IDR, -1);
|
2007-10-16 23:26:11 -07:00
|
|
|
ssc_readl(ssc->regs, SR);
|
2013-06-07 09:26:09 -07:00
|
|
|
clk_disable_unprepare(ssc->clk);
|
2007-10-16 23:26:11 -07:00
|
|
|
|
|
|
|
ssc->irq = platform_get_irq(pdev, 0);
|
|
|
|
if (!ssc->irq) {
|
|
|
|
dev_dbg(&pdev->dev, "could not get irq\n");
|
2012-10-15 20:56:58 -07:00
|
|
|
return -ENXIO;
|
2007-10-16 23:26:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock(&user_lock);
|
|
|
|
list_add_tail(&ssc->list, &ssc_list);
|
|
|
|
spin_unlock(&user_lock);
|
|
|
|
|
|
|
|
platform_set_drvdata(pdev, ssc);
|
|
|
|
|
|
|
|
dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
|
|
|
|
ssc->regs, ssc->irq);
|
|
|
|
|
2012-10-15 20:56:58 -07:00
|
|
|
return 0;
|
2007-10-16 23:26:11 -07:00
|
|
|
}
|
|
|
|
|
2012-11-19 11:26:02 -07:00
|
|
|
static int ssc_remove(struct platform_device *pdev)
|
2007-10-16 23:26:11 -07:00
|
|
|
{
|
|
|
|
struct ssc_device *ssc = platform_get_drvdata(pdev);
|
|
|
|
|
|
|
|
spin_lock(&user_lock);
|
|
|
|
list_del(&ssc->list);
|
|
|
|
spin_unlock(&user_lock);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct platform_driver ssc_driver = {
|
|
|
|
.driver = {
|
|
|
|
.name = "ssc",
|
2008-04-15 14:34:33 -07:00
|
|
|
.owner = THIS_MODULE,
|
2012-11-06 20:41:41 -07:00
|
|
|
.of_match_table = of_match_ptr(atmel_ssc_dt_ids),
|
2007-10-16 23:26:11 -07:00
|
|
|
},
|
2012-11-05 22:57:51 -07:00
|
|
|
.id_table = atmel_ssc_devtypes,
|
2012-10-15 20:56:59 -07:00
|
|
|
.probe = ssc_probe,
|
Sound updates for 3.8-rc1
This update contains a fairly wide range of changes all over in sound
subdirectory, mainly because of UAPI header moves by David and __dev*
annotation removals by Bill. Other highlights are:
- Introduced the support for wallclock timestamps in ALSA PCM core
- Add the poll loop implementation for HD-audio jack detection
- Yet more VGA-switcheroo fixes for HD-audio
- New VIA HD-audio codec support
- More fixes on resource management in USB audio and MIDI drivers
- More quirks for USB-audio ASUS Xonar U3, Reloop Play, Focusrite,
Roland VG-99, etc
- Add support for FastTrack C400 usb-audio
- Clean ups in many drivers regarding firmware loading
- Add PSC724 Ultiimate Edge support to ice1712
- A few hdspm driver updates
- New Stanton SCS.1d/1m FireWire driver
- Standardisation of the logging in ASoC codes
- DT and dmaengine support for ASoC Atmel
- Support for Wolfson ADSP cores
- New drivers for Freescale/iVeia P1022 and Maxim MAX98090
- Lots of other ASoC driver fixes and developments
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
iQIcBAABAgAGBQJQyYh9AAoJEGwxgFQ9KSmk95UP+wcVXRynWulCVwEnVjjWv/UM
2fIsD0RkWO4WoqEVCNCHzW27pvFC36uqLx5vtas4CoJ2CX8ufQsPqWTx6K3MY/DQ
/VJT8CI2EKPQY1Q0PySVo2nBqwcUXWWoZE47t1ZowR6cxtmgrS8lLxYJvkbfEOHF
PS8WItACqH5F5VPxGFkhPwR2OTLfaYt7ilKx82vgxSzdMAel8q/I9uS/MUv8KV+1
1s5yBvlW5eyDXKpQbP/KiMJLJ/zk1MRAKK2HftAk8pNt+Xy160NvXhbILDWKC4uT
QBRPqyIe8BmL3VlXpw3mn7nbeU7rSfc/Rbrnm2+Yb54/Wtj4PnV6Z6bg7HO610im
e/tBNHoaL7qn1iNYSC3heW11rToksd03/LK0GREvkX3Bl21T+Naaun/DY/PGIfMQ
nOXy7uVo6sVdZnN2MTWof9qeMYBSlrwQVsMde6kbYadNcXnuqUqCOx41kiAdE8t5
jfZy5QR+uDjdJgDv8/CuiCYxSjjTUfO1tdSV/VjsTK17Gfw3DWTJpeznVnoIALbZ
81HXYxb+uGZ8xDr0WXGkydlnPvB6bnWu2vvfrLBkioA/p60EDNCtgKo1y3NzQGh8
P2qILNhXIRrS2EoAScQOb6F1RPsvbDN9PbihnkShX3r7DXyeynr9jgPy3L2vf0bR
xyu0jtQiqYb34ss7qqdz
=IIsz
-----END PGP SIGNATURE-----
Merge tag 'sound-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai:
"This update contains a fairly wide range of changes all over in sound
subdirectory, mainly because of UAPI header moves by David and __dev*
annotation removals by Bill. Other highlights are:
- Introduced the support for wallclock timestamps in ALSA PCM core
- Add the poll loop implementation for HD-audio jack detection
- Yet more VGA-switcheroo fixes for HD-audio
- New VIA HD-audio codec support
- More fixes on resource management in USB audio and MIDI drivers
- More quirks for USB-audio ASUS Xonar U3, Reloop Play, Focusrite,
Roland VG-99, etc
- Add support for FastTrack C400 usb-audio
- Clean ups in many drivers regarding firmware loading
- Add PSC724 Ultiimate Edge support to ice1712
- A few hdspm driver updates
- New Stanton SCS.1d/1m FireWire driver
- Standardisation of the logging in ASoC codes
- DT and dmaengine support for ASoC Atmel
- Support for Wolfson ADSP cores
- New drivers for Freescale/iVeia P1022 and Maxim MAX98090
- Lots of other ASoC driver fixes and developments"
Fix up trivial conflicts. And go out on a limb and assume the dts file
'status' field of one of the conflicting things was supposed to be
"disabled", not "disable" like in pretty much all other cases.
* tag 'sound-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (341 commits)
ALSA: hda - Move runtime PM check to runtime_idle callback
ALSA: hda - Add stereo-dmic fixup for Acer Aspire One 522
ALSA: hda - Avoid doubly suspend after vga switcheroo
ALSA: usb-audio: Enable S/PDIF on the ASUS Xonar U3
ALSA: hda - Check validity of CORB/RIRB WP reads
ALSA: hda - use usleep_range in link reset and change timeout check
ALSA: HDA: VIA: Add support for codec VT1808.
ALSA: HDA: VIA Add support for codec VT1705CF.
ASoC: codecs: remove __dev* attributes
ASoC: utils: remove __dev* attributes
ASoC: ux500: remove __dev* attributes
ASoC: txx9: remove __dev* attributes
ASoC: tegra: remove __dev* attributes
ASoC: spear: remove __dev* attributes
ASoC: sh: remove __dev* attributes
ASoC: s6000: remove __dev* attributes
ASoC: OMAP: remove __dev* attributes
ASoC: nuc900: remove __dev* attributes
ASoC: mxs: remove __dev* attributes
ASoC: kirkwood: remove __dev* attributes
...
2012-12-13 12:51:23 -07:00
|
|
|
.remove = ssc_remove,
|
2007-10-16 23:26:11 -07:00
|
|
|
};
|
2012-10-15 20:56:59 -07:00
|
|
|
module_platform_driver(ssc_driver);
|
2007-10-16 23:26:11 -07:00
|
|
|
|
|
|
|
MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
|
|
|
|
MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");
|
|
|
|
MODULE_LICENSE("GPL");
|
2008-04-15 14:34:33 -07:00
|
|
|
MODULE_ALIAS("platform:ssc");
|