blob: 9b8346d3508a6a45a52a2b963f4e1521d1036a6f [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/platform_device.h>
16#include <linux/clk.h>
17#include <linux/err.h>
18#include <linux/debugfs.h>
19#include <linux/slab.h>
20#include <asm/uaccess.h>
21#include <mach/qdsp6v2/audio_dev_ctl.h>
22#include <mach/debug_mm.h>
23#include <sound/q6afe.h>
24#include <sound/apr_audio.h>
25#include "snddev_hdmi.h"
26
27static DEFINE_MUTEX(snddev_hdmi_lock);
28static int snddev_hdmi_active;
29
30static int snddev_hdmi_open(struct msm_snddev_info *dev_info)
31{
32 int rc = 0;
33 union afe_port_config afe_config;
34 struct snddev_hdmi_data *snddev_hdmi_data;
35
36 if (!dev_info) {
37 pr_err("msm_snddev_info is null\n");
38 return -EINVAL;
39 }
40
41 snddev_hdmi_data = dev_info->private_data;
42
43 mutex_lock(&snddev_hdmi_lock);
44
45 if (snddev_hdmi_active) {
46 pr_err("HDMI snddev already active\n");
47 mutex_unlock(&snddev_hdmi_lock);
48 return -EBUSY;
49 }
50
51 if (snddev_hdmi_data->on_apps) {
52 snddev_hdmi_active = 1;
53 pr_debug("%s open done\n", dev_info->name);
54 mutex_unlock(&snddev_hdmi_lock);
55 return 0;
56 }
57
58 afe_config.hdmi.channel_mode = snddev_hdmi_data->channel_mode;
59 afe_config.hdmi.bitwidth = 16;
60 afe_config.hdmi.data_type = 0;
61 rc = afe_open(snddev_hdmi_data->copp_id, &afe_config,
62 dev_info->sample_rate);
63
64 if (rc < 0) {
65 pr_err("afe_open failed\n");
66 mutex_unlock(&snddev_hdmi_lock);
67 return -EINVAL;
68 }
69 snddev_hdmi_active = 1;
70
71 pr_debug("%s open done\n", dev_info->name);
72
73 mutex_unlock(&snddev_hdmi_lock);
74
75 return 0;
76}
77
78static int snddev_hdmi_close(struct msm_snddev_info *dev_info)
79{
80
81 struct snddev_hdmi_data *snddev_hdmi_data;
82
83 if (!dev_info) {
84 pr_err("msm_snddev_info is null\n");
85 return -EINVAL;
86 }
87
88 snddev_hdmi_data = dev_info->private_data;
89
90 if (!dev_info->opened) {
91 pr_err("calling close device with out opening the"
92 " device\n");
93 return -EPERM;
94 }
95 mutex_lock(&snddev_hdmi_lock);
96
97 if (!snddev_hdmi_active) {
98 pr_err("HDMI snddev not active\n");
99 mutex_unlock(&snddev_hdmi_lock);
100 return -EPERM;
101 }
102 snddev_hdmi_active = 0;
103
104 if (snddev_hdmi_data->on_apps) {
Deepa Madiregama6a3a01a2011-10-28 06:34:17 +0530105 pr_debug("%s Closed\n", dev_info->name);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700106
107 mutex_unlock(&snddev_hdmi_lock);
108 return 0;
109 }
110
111
112 afe_close(HDMI_RX);
113
114 pr_debug("%s closed\n", dev_info->name);
115 mutex_unlock(&snddev_hdmi_lock);
116
117 return 0;
118}
119
120static int snddev_hdmi_set_freq(struct msm_snddev_info *dev_info, u32 req_freq)
121{
122 if (req_freq != 48000) {
123 pr_debug("Unsupported Frequency:%d\n", req_freq);
124 return -EINVAL;
125 }
126 return 48000;
127}
128
129static int snddev_hdmi_probe(struct platform_device *pdev)
130{
131 int rc = 0;
132 struct snddev_hdmi_data *pdata;
133 struct msm_snddev_info *dev_info;
134
135 if (!pdev || !pdev->dev.platform_data) {
136 printk(KERN_ALERT "Invalid caller\n");
137 return -ENODEV;
138 }
139
140 pdata = pdev->dev.platform_data;
141 if (!(pdata->capability & SNDDEV_CAP_RX)) {
142 pr_err("invalid device data either RX or TX\n");
143 return -ENODEV;
144 }
145
146 dev_info = kzalloc(sizeof(struct msm_snddev_info), GFP_KERNEL);
147 if (!dev_info) {
148 pr_err("unable to allocate memeory for msm_snddev_info\n");
149 return -ENOMEM;
150 }
151
152 dev_info->name = pdata->name;
153 dev_info->copp_id = pdata->copp_id;
154 dev_info->acdb_id = pdata->acdb_id;
155 dev_info->private_data = (void *)pdata;
156 dev_info->dev_ops.open = snddev_hdmi_open;
157 dev_info->dev_ops.close = snddev_hdmi_close;
158 dev_info->dev_ops.set_freq = snddev_hdmi_set_freq;
159 dev_info->capability = pdata->capability;
160 dev_info->opened = 0;
161 msm_snddev_register(dev_info);
162 dev_info->sample_rate = pdata->default_sample_rate;
163
164 pr_debug("probe done for %s\n", pdata->name);
165 return rc;
166}
167
168static struct platform_driver snddev_hdmi_driver = {
169 .probe = snddev_hdmi_probe,
170 .driver = {.name = "snddev_hdmi"}
171};
172
173static int __init snddev_hdmi_init(void)
174{
175 s32 rc;
176
177 rc = platform_driver_register(&snddev_hdmi_driver);
178 if (IS_ERR_VALUE(rc)) {
179
180 pr_err("platform_driver_register failed.\n");
181 goto error_platform_driver;
182 }
183
184 pr_debug("snddev_hdmi_init : done\n");
185
186 return 0;
187
188error_platform_driver:
189
190 pr_err("encounterd error\n");
191 return -ENODEV;
192}
193
194module_init(snddev_hdmi_init);
195
196MODULE_DESCRIPTION("HDMI Sound Device driver");
197MODULE_VERSION("1.0");
198MODULE_LICENSE("GPL v2");