diff options
Diffstat (limited to 'drivers/video/tegra/dc/dc_sysfs.c')
-rw-r--r-- | drivers/video/tegra/dc/dc_sysfs.c | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/drivers/video/tegra/dc/dc_sysfs.c b/drivers/video/tegra/dc/dc_sysfs.c new file mode 100644 index 00000000000..6bb18382e6e --- /dev/null +++ b/drivers/video/tegra/dc/dc_sysfs.c | |||
@@ -0,0 +1,327 @@ | |||
1 | /* | ||
2 | * drivers/video/tegra/dc/dc_sysfs.c | ||
3 | * | ||
4 | * Copyright (c) 2011, NVIDIA Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/kernel.h> | ||
23 | |||
24 | #include <mach/dc.h> | ||
25 | #include <mach/fb.h> | ||
26 | |||
27 | #include "dc_reg.h" | ||
28 | #include "dc_priv.h" | ||
29 | #include "nvsd.h" | ||
30 | |||
31 | static ssize_t mode_show(struct device *device, | ||
32 | struct device_attribute *attr, char *buf) | ||
33 | { | ||
34 | struct nvhost_device *ndev = to_nvhost_device(device); | ||
35 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
36 | struct tegra_dc_mode *m; | ||
37 | ssize_t res; | ||
38 | |||
39 | mutex_lock(&dc->lock); | ||
40 | m = &dc->mode; | ||
41 | res = snprintf(buf, PAGE_SIZE, | ||
42 | "pclk: %d\n" | ||
43 | "h_ref_to_sync: %d\n" | ||
44 | "v_ref_to_sync: %d\n" | ||
45 | "h_sync_width: %d\n" | ||
46 | "v_sync_width: %d\n" | ||
47 | "h_back_porch: %d\n" | ||
48 | "v_back_porch: %d\n" | ||
49 | "h_active: %d\n" | ||
50 | "v_active: %d\n" | ||
51 | "h_front_porch: %d\n" | ||
52 | "v_front_porch: %d\n" | ||
53 | "stereo_mode: %d\n", | ||
54 | m->pclk, m->h_ref_to_sync, m->v_ref_to_sync, | ||
55 | m->h_sync_width, m->v_sync_width, | ||
56 | m->h_back_porch, m->v_back_porch, | ||
57 | m->h_active, m->v_active, | ||
58 | m->h_front_porch, m->v_front_porch, | ||
59 | m->stereo_mode); | ||
60 | mutex_unlock(&dc->lock); | ||
61 | |||
62 | return res; | ||
63 | } | ||
64 | |||
65 | static DEVICE_ATTR(mode, S_IRUGO, mode_show, NULL); | ||
66 | |||
67 | static ssize_t stats_enable_show(struct device *dev, | ||
68 | struct device_attribute *attr, char *buf) | ||
69 | { | ||
70 | struct nvhost_device *ndev = to_nvhost_device(dev); | ||
71 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
72 | bool enabled; | ||
73 | |||
74 | if (mutex_lock_killable(&dc->lock)) | ||
75 | return -EINTR; | ||
76 | enabled = tegra_dc_stats_get(dc); | ||
77 | mutex_unlock(&dc->lock); | ||
78 | |||
79 | return snprintf(buf, PAGE_SIZE, "%d", enabled); | ||
80 | } | ||
81 | |||
82 | static ssize_t stats_enable_store(struct device *dev, | ||
83 | struct device_attribute *attr, const char *buf, size_t count) | ||
84 | { | ||
85 | struct nvhost_device *ndev = to_nvhost_device(dev); | ||
86 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
87 | unsigned long val = 0; | ||
88 | |||
89 | if (strict_strtoul(buf, 10, &val) < 0) | ||
90 | return -EINVAL; | ||
91 | |||
92 | if (mutex_lock_killable(&dc->lock)) | ||
93 | return -EINTR; | ||
94 | tegra_dc_stats_enable(dc, !!val); | ||
95 | mutex_unlock(&dc->lock); | ||
96 | |||
97 | return count; | ||
98 | } | ||
99 | |||
100 | static DEVICE_ATTR(stats_enable, S_IRUGO|S_IWUSR, | ||
101 | stats_enable_show, stats_enable_store); | ||
102 | |||
103 | static ssize_t enable_show(struct device *device, | ||
104 | struct device_attribute *attr, char *buf) | ||
105 | { | ||
106 | struct nvhost_device *ndev = to_nvhost_device(device); | ||
107 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
108 | ssize_t res; | ||
109 | |||
110 | mutex_lock(&dc->lock); | ||
111 | res = snprintf(buf, PAGE_SIZE, "%d\n", dc->enabled); | ||
112 | mutex_unlock(&dc->lock); | ||
113 | return res; | ||
114 | } | ||
115 | |||
116 | static ssize_t enable_store(struct device *dev, | ||
117 | struct device_attribute *attr, const char *buf, size_t count) | ||
118 | { | ||
119 | struct nvhost_device *ndev = to_nvhost_device(dev); | ||
120 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
121 | unsigned long val = 0; | ||
122 | |||
123 | if (strict_strtoul(buf, 10, &val) < 0) | ||
124 | return -EINVAL; | ||
125 | |||
126 | if (val) { | ||
127 | tegra_dc_enable(dc); | ||
128 | } else { | ||
129 | tegra_dc_disable(dc); | ||
130 | } | ||
131 | |||
132 | return count; | ||
133 | } | ||
134 | |||
135 | static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, enable_show, enable_store); | ||
136 | |||
137 | static ssize_t crc_checksum_latched_show(struct device *device, | ||
138 | struct device_attribute *attr, char *buf) | ||
139 | { | ||
140 | struct nvhost_device *ndev = to_nvhost_device(device); | ||
141 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
142 | |||
143 | u32 crc; | ||
144 | |||
145 | if (!dc->enabled) { | ||
146 | dev_err(&dc->ndev->dev, "Failed to get dc.\n"); | ||
147 | return -EFAULT; | ||
148 | } | ||
149 | |||
150 | crc = tegra_dc_read_checksum_latched(dc); | ||
151 | |||
152 | return snprintf(buf, PAGE_SIZE, "%u", crc); | ||
153 | } | ||
154 | |||
155 | static ssize_t crc_checksum_latched_store(struct device *dev, | ||
156 | struct device_attribute *attr, const char *buf, size_t count) | ||
157 | { | ||
158 | struct nvhost_device *ndev = to_nvhost_device(dev); | ||
159 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
160 | unsigned long val = 0; | ||
161 | |||
162 | if (!dc->enabled) { | ||
163 | dev_err(&dc->ndev->dev, "Failed to get dc.\n"); | ||
164 | return -EFAULT; | ||
165 | } | ||
166 | |||
167 | if (strict_strtoul(buf, 10, &val) < 0) | ||
168 | return -EINVAL; | ||
169 | |||
170 | if (val == 1) { | ||
171 | tegra_dc_enable_crc(dc); | ||
172 | dev_err(&dc->ndev->dev, "crc is enabled.\n"); | ||
173 | } else if (val == 0) { | ||
174 | tegra_dc_disable_crc(dc); | ||
175 | dev_err(&dc->ndev->dev, "crc is disabled.\n"); | ||
176 | } else | ||
177 | dev_err(&dc->ndev->dev, "Invalid input.\n"); | ||
178 | |||
179 | return count; | ||
180 | } | ||
181 | static DEVICE_ATTR(crc_checksum_latched, S_IRUGO|S_IWUSR, | ||
182 | crc_checksum_latched_show, crc_checksum_latched_store); | ||
183 | |||
184 | #define ORIENTATION_PORTRAIT "portrait" | ||
185 | #define ORIENTATION_LANDSCAPE "landscape" | ||
186 | |||
187 | static ssize_t orientation_3d_show(struct device *dev, | ||
188 | struct device_attribute *attr, char *buf) | ||
189 | { | ||
190 | struct nvhost_device *ndev = to_nvhost_device(dev); | ||
191 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
192 | struct tegra_dc_out *dc_out = dc->out; | ||
193 | const char *orientation; | ||
194 | switch (dc_out->stereo->orientation) { | ||
195 | case TEGRA_DC_STEREO_LANDSCAPE: | ||
196 | orientation = ORIENTATION_LANDSCAPE; | ||
197 | break; | ||
198 | case TEGRA_DC_STEREO_PORTRAIT: | ||
199 | orientation = ORIENTATION_PORTRAIT; | ||
200 | break; | ||
201 | default: | ||
202 | pr_err("Invalid value is stored for stereo_orientation.\n"); | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | return snprintf(buf, PAGE_SIZE, "%s\n", orientation); | ||
206 | } | ||
207 | |||
208 | static ssize_t orientation_3d_store(struct device *dev, | ||
209 | struct device_attribute *attr, const char *buf, size_t cnt) | ||
210 | { | ||
211 | struct nvhost_device *ndev = to_nvhost_device(dev); | ||
212 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
213 | struct tegra_dc_out *dc_out = dc->out; | ||
214 | struct tegra_stereo_out *stereo = dc_out->stereo; | ||
215 | int orientation; | ||
216 | |||
217 | if (0 == strncmp(buf, ORIENTATION_PORTRAIT, | ||
218 | min(cnt, ARRAY_SIZE(ORIENTATION_PORTRAIT) - 1))) { | ||
219 | orientation = TEGRA_DC_STEREO_PORTRAIT; | ||
220 | } else if (0 == strncmp(buf, ORIENTATION_LANDSCAPE, | ||
221 | min(cnt, ARRAY_SIZE(ORIENTATION_LANDSCAPE) - 1))) { | ||
222 | orientation = TEGRA_DC_STEREO_LANDSCAPE; | ||
223 | } else { | ||
224 | pr_err("Invalid property value for stereo_orientation.\n"); | ||
225 | return -EINVAL; | ||
226 | } | ||
227 | stereo->orientation = orientation; | ||
228 | stereo->set_orientation(orientation); | ||
229 | return cnt; | ||
230 | } | ||
231 | |||
232 | static DEVICE_ATTR(stereo_orientation, | ||
233 | S_IRUGO|S_IWUSR, orientation_3d_show, orientation_3d_store); | ||
234 | |||
235 | #define MODE_2D "2d" | ||
236 | #define MODE_3D "3d" | ||
237 | |||
238 | static ssize_t mode_3d_show(struct device *dev, | ||
239 | struct device_attribute *attr, char *buf) | ||
240 | { | ||
241 | struct nvhost_device *ndev = to_nvhost_device(dev); | ||
242 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
243 | struct tegra_dc_out *dc_out = dc->out; | ||
244 | const char *mode; | ||
245 | switch (dc_out->stereo->mode_2d_3d) { | ||
246 | case TEGRA_DC_STEREO_MODE_2D: | ||
247 | mode = MODE_2D; | ||
248 | break; | ||
249 | case TEGRA_DC_STEREO_MODE_3D: | ||
250 | mode = MODE_3D; | ||
251 | break; | ||
252 | default: | ||
253 | pr_err("Invalid value is stored for stereo_mode.\n"); | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | return snprintf(buf, PAGE_SIZE, "%s\n", mode); | ||
257 | } | ||
258 | |||
259 | static ssize_t mode_3d_store(struct device *dev, | ||
260 | struct device_attribute *attr, const char *buf, size_t cnt) | ||
261 | { | ||
262 | struct nvhost_device *ndev = to_nvhost_device(dev); | ||
263 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
264 | struct tegra_dc_out *dc_out = dc->out; | ||
265 | struct tegra_stereo_out *stereo = dc_out->stereo; | ||
266 | int mode; | ||
267 | |||
268 | if (0 == strncmp(buf, MODE_2D, min(cnt, ARRAY_SIZE(MODE_2D) - 1))) { | ||
269 | mode = TEGRA_DC_STEREO_MODE_2D; | ||
270 | } else if (0 == strncmp(buf, MODE_3D, | ||
271 | min(cnt, ARRAY_SIZE(MODE_3D) - 1))) { | ||
272 | mode = TEGRA_DC_STEREO_MODE_3D; | ||
273 | } else { | ||
274 | pr_err("Invalid property value for stereo_mode.\n"); | ||
275 | return -EINVAL; | ||
276 | } | ||
277 | stereo->mode_2d_3d = mode; | ||
278 | stereo->set_mode(mode); | ||
279 | return cnt; | ||
280 | } | ||
281 | |||
282 | static DEVICE_ATTR(stereo_mode, | ||
283 | S_IRUGO|S_IWUSR, mode_3d_show, mode_3d_store); | ||
284 | |||
285 | void __devexit tegra_dc_remove_sysfs(struct device *dev) | ||
286 | { | ||
287 | struct nvhost_device *ndev = to_nvhost_device(dev); | ||
288 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
289 | struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings; | ||
290 | |||
291 | device_remove_file(dev, &dev_attr_mode); | ||
292 | device_remove_file(dev, &dev_attr_enable); | ||
293 | device_remove_file(dev, &dev_attr_stats_enable); | ||
294 | device_remove_file(dev, &dev_attr_crc_checksum_latched); | ||
295 | |||
296 | if (dc->out->stereo) { | ||
297 | device_remove_file(dev, &dev_attr_stereo_orientation); | ||
298 | device_remove_file(dev, &dev_attr_stereo_mode); | ||
299 | } | ||
300 | |||
301 | if (sd_settings) | ||
302 | nvsd_remove_sysfs(dev); | ||
303 | } | ||
304 | |||
305 | void tegra_dc_create_sysfs(struct device *dev) | ||
306 | { | ||
307 | struct nvhost_device *ndev = to_nvhost_device(dev); | ||
308 | struct tegra_dc *dc = nvhost_get_drvdata(ndev); | ||
309 | struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings; | ||
310 | int error = 0; | ||
311 | |||
312 | error |= device_create_file(dev, &dev_attr_mode); | ||
313 | error |= device_create_file(dev, &dev_attr_enable); | ||
314 | error |= device_create_file(dev, &dev_attr_stats_enable); | ||
315 | error |= device_create_file(dev, &dev_attr_crc_checksum_latched); | ||
316 | |||
317 | if (dc->out->stereo) { | ||
318 | error |= device_create_file(dev, &dev_attr_stereo_orientation); | ||
319 | error |= device_create_file(dev, &dev_attr_stereo_mode); | ||
320 | } | ||
321 | |||
322 | if (sd_settings) | ||
323 | error |= nvsd_create_sysfs(dev); | ||
324 | |||
325 | if (error) | ||
326 | dev_err(&ndev->dev, "Failed to create sysfs attributes!\n"); | ||
327 | } | ||