e28d233b8e0bfafb49770238181f8a7e431f7ac1
[linux-3.10.git] / drivers / video / tegra / dc / dc_sysfs.c
1 /*
2  * drivers/video/tegra/dc/dc_sysfs.c
3  *
4  * Copyright (c) 2011-2013, NVIDIA CORPORATION, All rights reserved.
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/fb.h>
22 #include <linux/platform_device.h>
23 #include <linux/kernel.h>
24
25 #include <mach/dc.h>
26 #include <mach/fb.h>
27
28 #include <linux/nvmap.h>
29 #include "dc_reg.h"
30 #include "dc_priv.h"
31 #include "nvsd.h"
32
33 static ssize_t mode_show(struct device *device,
34         struct device_attribute *attr, char *buf)
35 {
36         struct platform_device *ndev = to_platform_device(device);
37         struct tegra_dc *dc = platform_get_drvdata(ndev);
38         struct tegra_dc_mode *m;
39         ssize_t res;
40
41         mutex_lock(&dc->lock);
42         m = &dc->mode;
43         res = snprintf(buf, PAGE_SIZE,
44                 "pclk: %d\n"
45                 "h_ref_to_sync: %d\n"
46                 "v_ref_to_sync: %d\n"
47                 "h_sync_width: %d\n"
48                 "v_sync_width: %d\n"
49                 "h_back_porch: %d\n"
50                 "v_back_porch: %d\n"
51                 "h_active: %d\n"
52                 "v_active: %d\n"
53                 "h_front_porch: %d\n"
54                 "v_front_porch: %d\n"
55                 "stereo_mode: %d\n",
56                 m->pclk, m->h_ref_to_sync, m->v_ref_to_sync,
57                 m->h_sync_width, m->v_sync_width,
58                 m->h_back_porch, m->v_back_porch,
59                 m->h_active, m->v_active,
60                 m->h_front_porch, m->v_front_porch,
61                 m->stereo_mode);
62         mutex_unlock(&dc->lock);
63
64         return res;
65 }
66
67 static DEVICE_ATTR(mode, S_IRUGO, mode_show, NULL);
68
69 static ssize_t stats_enable_show(struct device *dev,
70         struct device_attribute *attr, char *buf)
71 {
72         struct platform_device *ndev = to_platform_device(dev);
73         struct tegra_dc *dc = platform_get_drvdata(ndev);
74         bool enabled;
75
76         if (mutex_lock_killable(&dc->lock))
77                 return -EINTR;
78         enabled = tegra_dc_stats_get(dc);
79         mutex_unlock(&dc->lock);
80
81         return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
82 }
83
84 static ssize_t stats_enable_store(struct device *dev,
85         struct device_attribute *attr, const char *buf, size_t count)
86 {
87         struct platform_device *ndev = to_platform_device(dev);
88         struct tegra_dc *dc = platform_get_drvdata(ndev);
89         unsigned long val = 0;
90
91         if (strict_strtoul(buf, 10, &val) < 0)
92                 return -EINVAL;
93
94         if (mutex_lock_killable(&dc->lock))
95                 return -EINTR;
96         tegra_dc_stats_enable(dc, !!val);
97         mutex_unlock(&dc->lock);
98
99         return count;
100 }
101
102 static DEVICE_ATTR(stats_enable, S_IRUGO|S_IWUSR,
103         stats_enable_show, stats_enable_store);
104
105 static ssize_t enable_show(struct device *device,
106         struct device_attribute *attr, char *buf)
107 {
108         struct platform_device *ndev = to_platform_device(device);
109         struct tegra_dc *dc = platform_get_drvdata(ndev);
110         ssize_t res;
111
112         mutex_lock(&dc->lock);
113         res = snprintf(buf, PAGE_SIZE, "%d\n", dc->enabled);
114         mutex_unlock(&dc->lock);
115         return res;
116 }
117
118 static ssize_t enable_store(struct device *dev,
119         struct device_attribute *attr, const char *buf, size_t count)
120 {
121         struct platform_device *ndev = to_platform_device(dev);
122         struct tegra_dc *dc = platform_get_drvdata(ndev);
123         unsigned long val = 0;
124
125         if (strict_strtoul(buf, 10, &val) < 0)
126                 return -EINVAL;
127
128         if (val) {
129                 tegra_dc_enable(dc);
130         } else {
131                 tegra_dc_disable(dc);
132         }
133
134         return count;
135 }
136
137 static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, enable_show, enable_store);
138
139 #ifdef CONFIG_TEGRA_DC_WIN_H
140 static ssize_t win_h_show(struct device *device,
141         struct device_attribute *attr, char *buf)
142 {
143         struct platform_device *ndev = to_platform_device(device);
144         struct tegra_dc *dc = platform_get_drvdata(ndev);
145         unsigned long val = 0;
146
147         mutex_lock(&dc->lock);
148         tegra_dc_io_start(dc);
149
150         val = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
151
152         tegra_dc_io_end(dc);
153         mutex_unlock(&dc->lock);
154
155         return snprintf(buf, PAGE_SIZE, "%u\n", !!(val & WINH_CURS_SELECT(1)));
156 }
157
158 /* win_h sysfs controls hybrid window.
159  *
160  * 0 = cursor mode and 1 = window mode (default on T14x) */
161 static ssize_t win_h_store(struct device *dev,
162         struct device_attribute *attr, const char *buf, size_t count)
163 {
164         struct platform_device *ndev = to_platform_device(dev);
165         struct tegra_dc *dc = platform_get_drvdata(ndev);
166         unsigned int val = 0;
167         unsigned long cursor_val = 0;
168
169         if (!dc->enabled) {
170                 dev_err(&dc->ndev->dev, "%s: DC not enabled.\n", __func__);
171                 return -EFAULT;
172         }
173
174         if (kstrtouint(buf, 10, &val) < 0)
175                 return -EINVAL;
176
177         mutex_lock(&dc->lock);
178         tegra_dc_io_start(dc);
179
180         cursor_val = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
181         cursor_val &= ~WINH_CURS_SELECT(1);
182         if (val)
183                 cursor_val |= WINH_CURS_SELECT(1);
184         tegra_dc_writel(dc, cursor_val, DC_DISP_BLEND_CURSOR_CONTROL);
185
186         tegra_dc_io_end(dc);
187         mutex_unlock(&dc->lock);
188
189         return count;
190 }
191
192 static DEVICE_ATTR(win_h, S_IRUGO|S_IWUSR, win_h_show, win_h_store);
193 #endif
194
195 static ssize_t crc_checksum_latched_show(struct device *device,
196         struct device_attribute *attr, char *buf)
197 {
198         struct platform_device *ndev = to_platform_device(device);
199         struct tegra_dc *dc = platform_get_drvdata(ndev);
200
201         u32 crc;
202
203         if (!dc->enabled) {
204                 dev_err(&dc->ndev->dev, "%s: DC not enabled.\n", __func__);
205                 return -EFAULT;
206         }
207
208         crc = tegra_dc_read_checksum_latched(dc);
209
210         return snprintf(buf, PAGE_SIZE, "%u\n", crc);
211 }
212
213 static ssize_t crc_checksum_latched_store(struct device *dev,
214         struct device_attribute *attr, const char *buf, size_t count)
215 {
216         struct platform_device *ndev = to_platform_device(dev);
217         struct tegra_dc *dc = platform_get_drvdata(ndev);
218         unsigned long val = 0;
219
220         if (!dc->enabled) {
221                 dev_err(&dc->ndev->dev, "%s: DC not enabled.\n", __func__);
222                 return -EFAULT;
223         }
224
225         if (strict_strtoul(buf, 10, &val) < 0)
226                 return -EINVAL;
227
228         if (val == 1) {
229                 tegra_dc_enable_crc(dc);
230                 dev_dbg(&dc->ndev->dev, "crc is enabled.\n");
231         } else if (val == 0) {
232                 tegra_dc_disable_crc(dc);
233                 dev_dbg(&dc->ndev->dev, "crc is disabled.\n");
234         } else
235                 dev_err(&dc->ndev->dev, "Invalid input.\n");
236
237         return count;
238 }
239 static DEVICE_ATTR(crc_checksum_latched, S_IRUGO|S_IWUSR,
240                 crc_checksum_latched_show, crc_checksum_latched_store);
241
242 #define ORIENTATION_PORTRAIT    "portrait"
243 #define ORIENTATION_LANDSCAPE   "landscape"
244
245 static ssize_t orientation_3d_show(struct device *dev,
246         struct device_attribute *attr, char *buf)
247 {
248         struct platform_device *ndev = to_platform_device(dev);
249         struct tegra_dc *dc = platform_get_drvdata(ndev);
250         struct tegra_dc_out *dc_out = dc->out;
251         const char *orientation;
252         switch (dc_out->stereo->orientation) {
253         case TEGRA_DC_STEREO_LANDSCAPE:
254                 orientation = ORIENTATION_LANDSCAPE;
255                 break;
256         case TEGRA_DC_STEREO_PORTRAIT:
257                 orientation = ORIENTATION_PORTRAIT;
258                 break;
259         default:
260                 pr_err("Invalid value is stored for stereo_orientation.\n");
261                 return -EINVAL;
262         }
263         return snprintf(buf, PAGE_SIZE, "%s\n", orientation);
264 }
265
266 static ssize_t orientation_3d_store(struct device *dev,
267         struct device_attribute *attr, const char *buf, size_t cnt)
268 {
269         struct platform_device *ndev = to_platform_device(dev);
270         struct tegra_dc *dc = platform_get_drvdata(ndev);
271         struct tegra_dc_out *dc_out = dc->out;
272         struct tegra_stereo_out *stereo = dc_out->stereo;
273         int orientation;
274
275         if (0 == strncmp(buf, ORIENTATION_PORTRAIT,
276                         min(cnt, ARRAY_SIZE(ORIENTATION_PORTRAIT) - 1))) {
277                 orientation = TEGRA_DC_STEREO_PORTRAIT;
278         } else if (0 == strncmp(buf, ORIENTATION_LANDSCAPE,
279                         min(cnt, ARRAY_SIZE(ORIENTATION_LANDSCAPE) - 1))) {
280                 orientation = TEGRA_DC_STEREO_LANDSCAPE;
281         } else {
282                 pr_err("Invalid property value for stereo_orientation.\n");
283                 return -EINVAL;
284         }
285         stereo->orientation = orientation;
286         stereo->set_orientation(orientation);
287         return cnt;
288 }
289
290 static DEVICE_ATTR(stereo_orientation,
291         S_IRUGO|S_IWUSR, orientation_3d_show, orientation_3d_store);
292
293 #define MODE_2D         "2d"
294 #define MODE_3D         "3d"
295
296 static ssize_t mode_3d_show(struct device *dev,
297         struct device_attribute *attr, char *buf)
298 {
299         struct platform_device *ndev = to_platform_device(dev);
300         struct tegra_dc *dc = platform_get_drvdata(ndev);
301         struct tegra_dc_out *dc_out = dc->out;
302         const char *mode;
303         switch (dc_out->stereo->mode_2d_3d) {
304         case TEGRA_DC_STEREO_MODE_2D:
305                 mode = MODE_2D;
306                 break;
307         case TEGRA_DC_STEREO_MODE_3D:
308                 mode = MODE_3D;
309                 break;
310         default:
311                 pr_err("Invalid value is stored for stereo_mode.\n");
312                 return -EINVAL;
313         }
314         return snprintf(buf, PAGE_SIZE, "%s\n", mode);
315 }
316
317 static ssize_t mode_3d_store(struct device *dev,
318         struct device_attribute *attr, const char *buf, size_t cnt)
319 {
320         struct platform_device *ndev = to_platform_device(dev);
321         struct tegra_dc *dc = platform_get_drvdata(ndev);
322         struct tegra_dc_out *dc_out = dc->out;
323         struct tegra_stereo_out *stereo = dc_out->stereo;
324         int mode;
325
326         if (0 == strncmp(buf, MODE_2D, min(cnt, ARRAY_SIZE(MODE_2D) - 1))) {
327                 mode = TEGRA_DC_STEREO_MODE_2D;
328         } else if (0 == strncmp(buf, MODE_3D,
329                         min(cnt, ARRAY_SIZE(MODE_3D) - 1))) {
330                 mode = TEGRA_DC_STEREO_MODE_3D;
331         } else {
332                 pr_err("Invalid property value for stereo_mode.\n");
333                 return -EINVAL;
334         }
335         stereo->mode_2d_3d = mode;
336         stereo->set_mode(mode);
337         return cnt;
338 }
339
340 static DEVICE_ATTR(stereo_mode,
341         S_IRUGO|S_IWUSR, mode_3d_show, mode_3d_store);
342
343 static ssize_t nvdps_show(struct device *device,
344         struct device_attribute *attr, char *buf)
345 {
346         int refresh_rate;
347         struct platform_device *ndev = to_platform_device(device);
348         struct tegra_dc *dc = platform_get_drvdata(ndev);
349
350         refresh_rate = tegra_fb_get_mode(dc);
351         return snprintf(buf, PAGE_SIZE, "%d\n", refresh_rate);
352 }
353
354
355 static ssize_t nvdps_store(struct device *dev,
356         struct device_attribute *attr, const char *buf, size_t count)
357 {
358         struct platform_device *ndev = to_platform_device(dev);
359         struct tegra_dc *dc = platform_get_drvdata(ndev);
360         int refresh_rate;
361         int e;
362
363         e = kstrtoint(buf, 10, &refresh_rate);
364         if (e)
365                 return e;
366         e = tegra_fb_set_mode(dc, refresh_rate);
367
368         return count;
369 }
370
371 static DEVICE_ATTR(nvdps, S_IRUGO|S_IWUSR, nvdps_show, nvdps_store);
372
373 #ifdef CONFIG_TEGRA_DC_CMU
374 static ssize_t cmu_enable_store(struct device *dev,
375         struct device_attribute *attr, const char *buf, size_t count)
376 {
377         int val;
378         int e;
379         struct platform_device *ndev = to_platform_device(dev);
380         struct tegra_dc *dc = platform_get_drvdata(ndev);
381
382         e = kstrtoint(buf, 10, &val);
383         if (e)
384                 return e;
385
386         tegra_dc_cmu_enable(dc, val);
387
388         return count;
389 }
390
391 static ssize_t cmu_enable_show(struct device *dev,
392         struct device_attribute *attr, char *buf)
393 {
394         struct platform_device *ndev = to_platform_device(dev);
395         struct tegra_dc *dc = platform_get_drvdata(ndev);
396
397         return snprintf(buf, PAGE_SIZE, "%d\n", dc->pdata->cmu_enable);
398 }
399
400 static DEVICE_ATTR(cmu_enable,
401                 S_IRUGO|S_IWUSR, cmu_enable_show, cmu_enable_store);
402 #endif
403 static ssize_t smart_panel_show(struct device *device,
404         struct device_attribute *attr, char  *buf)
405 {
406         return snprintf(buf, PAGE_SIZE, "1\n");
407 }
408
409 static DEVICE_ATTR(smart_panel, S_IRUGO, smart_panel_show, NULL);
410
411 void tegra_dc_remove_sysfs(struct device *dev)
412 {
413         struct platform_device *ndev = to_platform_device(dev);
414         struct tegra_dc *dc = platform_get_drvdata(ndev);
415         struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
416
417         device_remove_file(dev, &dev_attr_mode);
418         device_remove_file(dev, &dev_attr_nvdps);
419         device_remove_file(dev, &dev_attr_enable);
420         device_remove_file(dev, &dev_attr_stats_enable);
421         device_remove_file(dev, &dev_attr_crc_checksum_latched);
422 #ifdef CONFIG_TEGRA_DC_WIN_H
423         device_remove_file(dev, &dev_attr_win_h);
424 #endif
425 #ifdef CONFIG_TEGRA_DC_CMU
426         device_remove_file(dev, &dev_attr_cmu_enable);
427 #endif
428
429         if (dc->out->stereo) {
430                 device_remove_file(dev, &dev_attr_stereo_orientation);
431                 device_remove_file(dev, &dev_attr_stereo_mode);
432         }
433
434         if (sd_settings)
435                 nvsd_remove_sysfs(dev);
436
437         if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
438                 device_remove_file(dev, &dev_attr_smart_panel);
439 }
440
441 void tegra_dc_create_sysfs(struct device *dev)
442 {
443         struct platform_device *ndev = to_platform_device(dev);
444         struct tegra_dc *dc = platform_get_drvdata(ndev);
445         struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
446         int error = 0;
447
448         error |= device_create_file(dev, &dev_attr_mode);
449         error |= device_create_file(dev, &dev_attr_nvdps);
450         error |= device_create_file(dev, &dev_attr_enable);
451         error |= device_create_file(dev, &dev_attr_stats_enable);
452         error |= device_create_file(dev, &dev_attr_crc_checksum_latched);
453 #ifdef CONFIG_TEGRA_DC_WIN_H
454         error |= device_create_file(dev, &dev_attr_win_h);
455 #endif
456 #ifdef CONFIG_TEGRA_DC_CMU
457         error |= device_create_file(dev, &dev_attr_cmu_enable);
458 #endif
459
460         if (dc->out->stereo) {
461                 error |= device_create_file(dev, &dev_attr_stereo_orientation);
462                 error |= device_create_file(dev, &dev_attr_stereo_mode);
463         }
464
465         if (sd_settings)
466                 error |= nvsd_create_sysfs(dev);
467
468         if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
469                 error |= device_create_file(dev, &dev_attr_smart_panel);
470
471         if (error)
472                 dev_err(&ndev->dev, "Failed to create sysfs attributes!\n");
473 }