irq_remap: disable IRQ remapping if any IOAPIC lacks an IOMMU
[pandora-kernel.git] / sound / soc / omap / omap-hdmi.c
1 /*
2  * omap-hdmi.c
3  *
4  * OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
5  * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
6  * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
7  *          Ricardo Neri <ricardo.neri@ti.com>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * version 2 as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/device.h>
28 #include <sound/core.h>
29 #include <sound/pcm.h>
30 #include <sound/pcm_params.h>
31 #include <sound/initval.h>
32 #include <sound/soc.h>
33
34 #include <plat/dma.h>
35 #include "omap-pcm.h"
36 #include "omap-hdmi.h"
37
38 #define DRV_NAME "hdmi-audio-dai"
39
40 static struct omap_pcm_dma_data omap_hdmi_dai_dma_params = {
41         .name = "HDMI playback",
42         .sync_mode = OMAP_DMA_SYNC_PACKET,
43 };
44
45 static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
46                                   struct snd_soc_dai *dai)
47 {
48         int err;
49         /*
50          * Make sure that the period bytes are multiple of the DMA packet size.
51          * Largest packet size we use is 32 32-bit words = 128 bytes
52          */
53         err = snd_pcm_hw_constraint_step(substream->runtime, 0,
54                                  SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
55         if (err < 0)
56                 return err;
57
58         return 0;
59 }
60
61 static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
62                                     struct snd_pcm_hw_params *params,
63                                     struct snd_soc_dai *dai)
64 {
65         int err = 0;
66
67         switch (params_format(params)) {
68         case SNDRV_PCM_FORMAT_S16_LE:
69                 omap_hdmi_dai_dma_params.packet_size = 16;
70                 break;
71         case SNDRV_PCM_FORMAT_S24_LE:
72                 omap_hdmi_dai_dma_params.packet_size = 32;
73                 break;
74         default:
75                 err = -EINVAL;
76         }
77
78         omap_hdmi_dai_dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
79
80         snd_soc_dai_set_dma_data(dai, substream,
81                                  &omap_hdmi_dai_dma_params);
82
83         return err;
84 }
85
86 static struct snd_soc_dai_ops omap_hdmi_dai_ops = {
87         .startup        = omap_hdmi_dai_startup,
88         .hw_params      = omap_hdmi_dai_hw_params,
89 };
90
91 static struct snd_soc_dai_driver omap_hdmi_dai = {
92         .playback = {
93                 .channels_min = 2,
94                 .channels_max = 2,
95                 .rates = OMAP_HDMI_RATES,
96                 .formats = OMAP_HDMI_FORMATS,
97         },
98         .ops = &omap_hdmi_dai_ops,
99 };
100
101 static __devinit int omap_hdmi_probe(struct platform_device *pdev)
102 {
103         int ret;
104         struct resource *hdmi_rsrc;
105
106         hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
107         if (!hdmi_rsrc) {
108                 dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n");
109                 return -EINVAL;
110         }
111
112         omap_hdmi_dai_dma_params.port_addr =  hdmi_rsrc->start
113                 + OMAP_HDMI_AUDIO_DMA_PORT;
114
115         hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0);
116         if (!hdmi_rsrc) {
117                 dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n");
118                 return -EINVAL;
119         }
120
121         omap_hdmi_dai_dma_params.dma_req =  hdmi_rsrc->start;
122
123         ret = snd_soc_register_dai(&pdev->dev, &omap_hdmi_dai);
124         return ret;
125 }
126
127 static int __devexit omap_hdmi_remove(struct platform_device *pdev)
128 {
129         snd_soc_unregister_dai(&pdev->dev);
130         return 0;
131 }
132
133 static struct platform_driver hdmi_dai_driver = {
134         .driver = {
135                 .name = DRV_NAME,
136                 .owner = THIS_MODULE,
137         },
138         .probe = omap_hdmi_probe,
139         .remove = __devexit_p(omap_hdmi_remove),
140 };
141
142 static int __init hdmi_dai_init(void)
143 {
144         return platform_driver_register(&hdmi_dai_driver);
145 }
146 module_init(hdmi_dai_init);
147
148 static void __exit hdmi_dai_exit(void)
149 {
150         platform_driver_unregister(&hdmi_dai_driver);
151 }
152 module_exit(hdmi_dai_exit);
153
154 MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@ti.com>");
155 MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
156 MODULE_DESCRIPTION("OMAP HDMI SoC Interface");
157 MODULE_LICENSE("GPL");
158 MODULE_ALIAS("platform:" DRV_NAME);