| OLD | NEW |
| 1 /* | 1 /* |
| 2 * smdk_spdif.c -- S/PDIF audio for SMDK | 2 * smdk_spdif.c -- S/PDIF audio for SMDK |
| 3 * | 3 * |
| 4 * Copyright 2010 Samsung Electronics Co. Ltd. | 4 * Copyright 2010 Samsung Electronics Co. Ltd. |
| 5 * | 5 * |
| 6 * This program is free software; you can redistribute it and/or | 6 * This program is free software; you can redistribute it and/or |
| 7 * modify it under the terms of the GNU General Public License as | 7 * modify it under the terms of the GNU General Public License as |
| 8 * published by the Free Software Foundation; either version 2 of the | 8 * published by the Free Software Foundation; either version 2 of the |
| 9 * License, or (at your option) any later version. | 9 * License, or (at your option) any later version. |
| 10 * | 10 * |
| 11 */ | 11 */ |
| 12 | 12 |
| 13 #include <linux/module.h> | |
| 14 #include <linux/device.h> | |
| 15 #include <linux/clk.h> | 13 #include <linux/clk.h> |
| 16 | 14 |
| 17 #include <plat/devs.h> | |
| 18 | |
| 19 #include <sound/soc.h> | 15 #include <sound/soc.h> |
| 20 | 16 |
| 21 #include "s3c-dma.h" | |
| 22 #include "spdif.h" | 17 #include "spdif.h" |
| 23 | 18 |
| 24 /* Audio clock settings are belonged to board specific part. Every | 19 /* Audio clock settings are belonged to board specific part. Every |
| 25 * board can set audio source clock setting which is matched with H/W | 20 * board can set audio source clock setting which is matched with H/W |
| 26 * like this function-'set_audio_clock_heirachy'. | 21 * like this function-'set_audio_clock_heirachy'. |
| 27 */ | 22 */ |
| 28 static int set_audio_clock_heirachy(struct platform_device *pdev) | 23 static int set_audio_clock_heirachy(struct platform_device *pdev) |
| 29 { | 24 { |
| 30 struct clk *fout_epll, *mout_epll, *sclk_audio0, *sclk_spdif; | 25 struct clk *fout_epll, *mout_epll, *sclk_audio0, *sclk_spdif; |
| 31 » int ret; | 26 » int ret = 0; |
| 32 | 27 |
| 33 fout_epll = clk_get(NULL, "fout_epll"); | 28 fout_epll = clk_get(NULL, "fout_epll"); |
| 34 if (IS_ERR(fout_epll)) { | 29 if (IS_ERR(fout_epll)) { |
| 35 printk(KERN_WARNING "%s: Cannot find fout_epll.\n", | 30 printk(KERN_WARNING "%s: Cannot find fout_epll.\n", |
| 36 __func__); | 31 __func__); |
| 37 return -EINVAL; | 32 return -EINVAL; |
| 38 } | 33 } |
| 39 | 34 |
| 40 mout_epll = clk_get(NULL, "mout_epll"); | 35 mout_epll = clk_get(NULL, "mout_epll"); |
| 41 if (IS_ERR(mout_epll)) { | 36 if (IS_ERR(mout_epll)) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 54 } | 49 } |
| 55 | 50 |
| 56 sclk_spdif = clk_get(NULL, "sclk_spdif"); | 51 sclk_spdif = clk_get(NULL, "sclk_spdif"); |
| 57 if (IS_ERR(sclk_spdif)) { | 52 if (IS_ERR(sclk_spdif)) { |
| 58 printk(KERN_WARNING "%s: Cannot find sclk_spdif.\n", | 53 printk(KERN_WARNING "%s: Cannot find sclk_spdif.\n", |
| 59 __func__); | 54 __func__); |
| 60 ret = -EINVAL; | 55 ret = -EINVAL; |
| 61 goto out3; | 56 goto out3; |
| 62 } | 57 } |
| 63 | 58 |
| 64 » /* Set audio clock heirachy for S/PDIF */ | 59 » /* Set audio clock hierarchy for S/PDIF */ |
| 65 clk_set_parent(mout_epll, fout_epll); | 60 clk_set_parent(mout_epll, fout_epll); |
| 66 clk_set_parent(sclk_audio0, mout_epll); | 61 clk_set_parent(sclk_audio0, mout_epll); |
| 67 clk_set_parent(sclk_spdif, sclk_audio0); | 62 clk_set_parent(sclk_spdif, sclk_audio0); |
| 68 | 63 |
| 69 clk_put(sclk_spdif); | 64 clk_put(sclk_spdif); |
| 70 out3: | 65 out3: |
| 71 clk_put(sclk_audio0); | 66 clk_put(sclk_audio0); |
| 72 out2: | 67 out2: |
| 73 clk_put(mout_epll); | 68 clk_put(mout_epll); |
| 74 out1: | 69 out1: |
| 75 clk_put(fout_epll); | 70 clk_put(fout_epll); |
| 76 | 71 |
| 77 return ret; | 72 return ret; |
| 78 } | 73 } |
| 79 | 74 |
| 80 /* We should haved to set clock directly on this part because of clock | 75 /* We should haved to set clock directly on this part because of clock |
| 81 * scheme of Samsudng SoCs did not support to set rates from abstrct | 76 * scheme of Samsudng SoCs did not support to set rates from abstrct |
| 82 * clock of it's heirachy. | 77 * clock of it's hierarchy. |
| 83 */ | 78 */ |
| 84 static int set_audio_clock_rate(unsigned long epll_rate, | 79 static int set_audio_clock_rate(unsigned long epll_rate, |
| 85 unsigned long audio_rate) | 80 unsigned long audio_rate) |
| 86 { | 81 { |
| 87 struct clk *fout_epll, *sclk_spdif; | 82 struct clk *fout_epll, *sclk_spdif; |
| 88 | 83 |
| 89 fout_epll = clk_get(NULL, "fout_epll"); | 84 fout_epll = clk_get(NULL, "fout_epll"); |
| 90 if (IS_ERR(fout_epll)) { | 85 if (IS_ERR(fout_epll)) { |
| 91 printk(KERN_ERR "%s: failed to get fout_epll\n", __func__); | 86 printk(KERN_ERR "%s: failed to get fout_epll\n", __func__); |
| 92 return -ENOENT; | 87 return -ENOENT; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 if (ret < 0) | 140 if (ret < 0) |
| 146 return ret; | 141 return ret; |
| 147 | 142 |
| 148 return ret; | 143 return ret; |
| 149 } | 144 } |
| 150 | 145 |
| 151 static struct snd_soc_ops smdk_spdif_ops = { | 146 static struct snd_soc_ops smdk_spdif_ops = { |
| 152 .hw_params = smdk_hw_params, | 147 .hw_params = smdk_hw_params, |
| 153 }; | 148 }; |
| 154 | 149 |
| 155 static struct snd_soc_card smdk; | |
| 156 | |
| 157 static struct snd_soc_dai_link smdk_dai = { | 150 static struct snd_soc_dai_link smdk_dai = { |
| 158 .name = "S/PDIF", | 151 .name = "S/PDIF", |
| 159 .stream_name = "S/PDIF PCM Playback", | 152 .stream_name = "S/PDIF PCM Playback", |
| 160 » .platform_name = "s3c24xx-pcm-audio", | 153 » .platform_name = "samsung-audio", |
| 161 .cpu_dai_name = "samsung-spdif", | 154 .cpu_dai_name = "samsung-spdif", |
| 162 .codec_dai_name = "dit-hifi", | 155 .codec_dai_name = "dit-hifi", |
| 163 .codec_name = "spdif-dit", | 156 .codec_name = "spdif-dit", |
| 164 .ops = &smdk_spdif_ops, | 157 .ops = &smdk_spdif_ops, |
| 165 }; | 158 }; |
| 166 | 159 |
| 167 static struct snd_soc_card smdk = { | 160 static struct snd_soc_card smdk = { |
| 168 .name = "SMDK-S/PDIF", | 161 .name = "SMDK-S/PDIF", |
| 169 .dai_link = &smdk_dai, | 162 .dai_link = &smdk_dai, |
| 170 .num_links = 1, | 163 .num_links = 1, |
| 171 }; | 164 }; |
| 172 | 165 |
| 173 static struct platform_device *smdk_snd_spdif_dit_device; | 166 static struct platform_device *smdk_snd_spdif_dit_device; |
| 174 static struct platform_device *smdk_snd_spdif_device; | 167 static struct platform_device *smdk_snd_spdif_device; |
| 175 | 168 |
| 176 static int __init smdk_init(void) | 169 static int __init smdk_init(void) |
| 177 { | 170 { |
| 178 int ret; | 171 int ret; |
| 179 | 172 |
| 180 smdk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1); | 173 smdk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1); |
| 181 if (!smdk_snd_spdif_dit_device) | 174 if (!smdk_snd_spdif_dit_device) |
| 182 return -ENOMEM; | 175 return -ENOMEM; |
| 183 | 176 |
| 184 ret = platform_device_add(smdk_snd_spdif_dit_device); | 177 ret = platform_device_add(smdk_snd_spdif_dit_device); |
| 185 if (ret) | 178 if (ret) |
| 186 » » goto err2; | 179 » » goto err1; |
| 187 | 180 |
| 188 smdk_snd_spdif_device = platform_device_alloc("soc-audio", -1); | 181 smdk_snd_spdif_device = platform_device_alloc("soc-audio", -1); |
| 189 if (!smdk_snd_spdif_device) { | 182 if (!smdk_snd_spdif_device) { |
| 190 ret = -ENOMEM; | 183 ret = -ENOMEM; |
| 191 goto err2; | 184 goto err2; |
| 192 } | 185 } |
| 193 | 186 |
| 194 platform_set_drvdata(smdk_snd_spdif_device, &smdk); | 187 platform_set_drvdata(smdk_snd_spdif_device, &smdk); |
| 195 | 188 |
| 196 ret = platform_device_add(smdk_snd_spdif_device); | 189 ret = platform_device_add(smdk_snd_spdif_device); |
| 197 if (ret) | 190 if (ret) |
| 198 » » goto err1; | 191 » » goto err3; |
| 199 | 192 |
| 200 » /* Set audio clock heirachy manually */ | 193 » /* Set audio clock hierarchy manually */ |
| 201 ret = set_audio_clock_heirachy(smdk_snd_spdif_device); | 194 ret = set_audio_clock_heirachy(smdk_snd_spdif_device); |
| 202 if (ret) | 195 if (ret) |
| 203 » » goto err1; | 196 » » goto err4; |
| 204 | 197 |
| 205 return 0; | 198 return 0; |
| 206 err1: | 199 err4: |
| 200 » platform_device_del(smdk_snd_spdif_device); |
| 201 err3: |
| 207 platform_device_put(smdk_snd_spdif_device); | 202 platform_device_put(smdk_snd_spdif_device); |
| 208 err2: | 203 err2: |
| 204 platform_device_del(smdk_snd_spdif_dit_device); |
| 205 err1: |
| 209 platform_device_put(smdk_snd_spdif_dit_device); | 206 platform_device_put(smdk_snd_spdif_dit_device); |
| 210 return ret; | 207 return ret; |
| 211 } | 208 } |
| 212 | 209 |
| 213 static void __exit smdk_exit(void) | 210 static void __exit smdk_exit(void) |
| 214 { | 211 { |
| 215 platform_device_unregister(smdk_snd_spdif_device); | 212 platform_device_unregister(smdk_snd_spdif_device); |
| 213 platform_device_unregister(smdk_snd_spdif_dit_device); |
| 216 } | 214 } |
| 217 | 215 |
| 218 module_init(smdk_init); | 216 module_init(smdk_init); |
| 219 module_exit(smdk_exit); | 217 module_exit(smdk_exit); |
| 220 | 218 |
| 221 MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>"); | 219 MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>"); |
| 222 MODULE_DESCRIPTION("ALSA SoC SMDK+S/PDIF"); | 220 MODULE_DESCRIPTION("ALSA SoC SMDK+S/PDIF"); |
| 223 MODULE_LICENSE("GPL"); | 221 MODULE_LICENSE("GPL"); |
| OLD | NEW |