aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/atmel-ssc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 14:51:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-13 14:51:23 -0500
commit046e7d685bc370fd4c879ab6635ad3f69e6673d1 (patch)
tree36b981f8d1f2bfd348c1479acbe3a9426d35c377 /drivers/misc/atmel-ssc.c
parentfe504c5c745aeb767d978fbedeb94775fd4cb69c (diff)
parent6eb827d23577a4efec2b10a9c4cc9ded268a1d1c (diff)
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 ...
Diffstat (limited to 'drivers/misc/atmel-ssc.c')
-rw-r--r--drivers/misc/atmel-ssc.c135
1 files changed, 88 insertions, 47 deletions
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index c58f9abcb356..158da5a81a66 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -18,6 +18,8 @@
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/module.h> 19#include <linux/module.h>
20 20
21#include <linux/of.h>
22
21/* Serialize access to ssc_list and user count */ 23/* Serialize access to ssc_list and user count */
22static DEFINE_SPINLOCK(user_lock); 24static DEFINE_SPINLOCK(user_lock);
23static LIST_HEAD(ssc_list); 25static LIST_HEAD(ssc_list);
@@ -29,7 +31,13 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
29 31
30 spin_lock(&user_lock); 32 spin_lock(&user_lock);
31 list_for_each_entry(ssc, &ssc_list, list) { 33 list_for_each_entry(ssc, &ssc_list, list) {
32 if (ssc->pdev->id == ssc_num) { 34 if (ssc->pdev->dev.of_node) {
35 if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc")
36 == ssc_num) {
37 ssc_valid = 1;
38 break;
39 }
40 } else if (ssc->pdev->id == ssc_num) {
33 ssc_valid = 1; 41 ssc_valid = 1;
34 break; 42 break;
35 } 43 }
@@ -68,39 +76,93 @@ void ssc_free(struct ssc_device *ssc)
68} 76}
69EXPORT_SYMBOL(ssc_free); 77EXPORT_SYMBOL(ssc_free);
70 78
71static int __init ssc_probe(struct platform_device *pdev) 79static struct atmel_ssc_platform_data at91rm9200_config = {
80 .use_dma = 0,
81};
82
83static struct atmel_ssc_platform_data at91sam9g45_config = {
84 .use_dma = 1,
85};
86
87static const struct platform_device_id atmel_ssc_devtypes[] = {
88 {
89 .name = "at91rm9200_ssc",
90 .driver_data = (unsigned long) &at91rm9200_config,
91 }, {
92 .name = "at91sam9g45_ssc",
93 .driver_data = (unsigned long) &at91sam9g45_config,
94 }, {
95 /* sentinel */
96 }
97};
98
99#ifdef CONFIG_OF
100static const struct of_device_id atmel_ssc_dt_ids[] = {
101 {
102 .compatible = "atmel,at91rm9200-ssc",
103 .data = &at91rm9200_config,
104 }, {
105 .compatible = "atmel,at91sam9g45-ssc",
106 .data = &at91sam9g45_config,
107 }, {
108 /* sentinel */
109 }
110};
111MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids);
112#endif
113
114static inline const struct atmel_ssc_platform_data * __init
115 atmel_ssc_get_driver_data(struct platform_device *pdev)
116{
117 if (pdev->dev.of_node) {
118 const struct of_device_id *match;
119 match = of_match_node(atmel_ssc_dt_ids, pdev->dev.of_node);
120 if (match == NULL)
121 return NULL;
122 return match->data;
123 }
124
125 return (struct atmel_ssc_platform_data *)
126 platform_get_device_id(pdev)->driver_data;
127}
128
129static int ssc_probe(struct platform_device *pdev)
72{ 130{
73 int retval = 0;
74 struct resource *regs; 131 struct resource *regs;
75 struct ssc_device *ssc; 132 struct ssc_device *ssc;
133 const struct atmel_ssc_platform_data *plat_dat;
76 134
77 ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL); 135 ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
78 if (!ssc) { 136 if (!ssc) {
79 dev_dbg(&pdev->dev, "out of memory\n"); 137 dev_dbg(&pdev->dev, "out of memory\n");
80 retval = -ENOMEM; 138 return -ENOMEM;
81 goto out;
82 } 139 }
83 140
141 ssc->pdev = pdev;
142
143 plat_dat = atmel_ssc_get_driver_data(pdev);
144 if (!plat_dat)
145 return -ENODEV;
146 ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat;
147
84 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 148 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
85 if (!regs) { 149 if (!regs) {
86 dev_dbg(&pdev->dev, "no mmio resource defined\n"); 150 dev_dbg(&pdev->dev, "no mmio resource defined\n");
87 retval = -ENXIO; 151 return -ENXIO;
88 goto out_free;
89 } 152 }
90 153
91 ssc->clk = clk_get(&pdev->dev, "pclk"); 154 ssc->regs = devm_request_and_ioremap(&pdev->dev, regs);
92 if (IS_ERR(ssc->clk)) {
93 dev_dbg(&pdev->dev, "no pclk clock defined\n");
94 retval = -ENXIO;
95 goto out_free;
96 }
97
98 ssc->pdev = pdev;
99 ssc->regs = ioremap(regs->start, resource_size(regs));
100 if (!ssc->regs) { 155 if (!ssc->regs) {
101 dev_dbg(&pdev->dev, "ioremap failed\n"); 156 dev_dbg(&pdev->dev, "ioremap failed\n");
102 retval = -EINVAL; 157 return -EINVAL;
103 goto out_clk; 158 }
159
160 ssc->phybase = regs->start;
161
162 ssc->clk = devm_clk_get(&pdev->dev, "pclk");
163 if (IS_ERR(ssc->clk)) {
164 dev_dbg(&pdev->dev, "no pclk clock defined\n");
165 return -ENXIO;
104 } 166 }
105 167
106 /* disable all interrupts */ 168 /* disable all interrupts */
@@ -112,8 +174,7 @@ static int __init ssc_probe(struct platform_device *pdev)
112 ssc->irq = platform_get_irq(pdev, 0); 174 ssc->irq = platform_get_irq(pdev, 0);
113 if (!ssc->irq) { 175 if (!ssc->irq) {
114 dev_dbg(&pdev->dev, "could not get irq\n"); 176 dev_dbg(&pdev->dev, "could not get irq\n");
115 retval = -ENXIO; 177 return -ENXIO;
116 goto out_unmap;
117 } 178 }
118 179
119 spin_lock(&user_lock); 180 spin_lock(&user_lock);
@@ -125,16 +186,7 @@ static int __init ssc_probe(struct platform_device *pdev)
125 dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n", 186 dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
126 ssc->regs, ssc->irq); 187 ssc->regs, ssc->irq);
127 188
128 goto out; 189 return 0;
129
130out_unmap:
131 iounmap(ssc->regs);
132out_clk:
133 clk_put(ssc->clk);
134out_free:
135 kfree(ssc);
136out:
137 return retval;
138} 190}
139 191
140static int ssc_remove(struct platform_device *pdev) 192static int ssc_remove(struct platform_device *pdev)
@@ -142,34 +194,23 @@ static int ssc_remove(struct platform_device *pdev)
142 struct ssc_device *ssc = platform_get_drvdata(pdev); 194 struct ssc_device *ssc = platform_get_drvdata(pdev);
143 195
144 spin_lock(&user_lock); 196 spin_lock(&user_lock);
145 iounmap(ssc->regs);
146 clk_put(ssc->clk);
147 list_del(&ssc->list); 197 list_del(&ssc->list);
148 kfree(ssc);
149 spin_unlock(&user_lock); 198 spin_unlock(&user_lock);
150 199
151 return 0; 200 return 0;
152} 201}
153 202
154static struct platform_driver ssc_driver = { 203static struct platform_driver ssc_driver = {
155 .remove = ssc_remove,
156 .driver = { 204 .driver = {
157 .name = "ssc", 205 .name = "ssc",
158 .owner = THIS_MODULE, 206 .owner = THIS_MODULE,
207 .of_match_table = of_match_ptr(atmel_ssc_dt_ids),
159 }, 208 },
209 .id_table = atmel_ssc_devtypes,
210 .probe = ssc_probe,
211 .remove = ssc_remove,
160}; 212};
161 213module_platform_driver(ssc_driver);
162static int __init ssc_init(void)
163{
164 return platform_driver_probe(&ssc_driver, ssc_probe);
165}
166module_init(ssc_init);
167
168static void __exit ssc_exit(void)
169{
170 platform_driver_unregister(&ssc_driver);
171}
172module_exit(ssc_exit);
173 214
174MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); 215MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
175MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91"); 216MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");