6b34c43529869cb44b48f2c989f83da281e18529
[linux-2.6.git] / drivers / video / tegra / dc / dc_sysfs.c
1 /*
2  * drivers/video/tegra/dc/dc_sysfs.c
3  *
4  * Copyright (c) 2011-2012, 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/../../drivers/video/tegra/nvmap/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", 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 static ssize_t crc_checksum_latched_show(struct device *device,
140         struct device_attribute *attr, char *buf)
141 {
142         struct platform_device *ndev = to_platform_device(device);
143         struct tegra_dc *dc = platform_get_drvdata(ndev);
144
145         u32 crc;
146
147         if (!dc->enabled) {
148                 dev_err(&dc->ndev->dev, "%s: DC not enabled.\n", __func__);
149                 return -EFAULT;
150         }
151
152         crc = tegra_dc_read_checksum_latched(dc);
153
154         return snprintf(buf, PAGE_SIZE, "%u", crc);
155 }
156
157 static ssize_t crc_checksum_latched_store(struct device *dev,
158         struct device_attribute *attr, const char *buf, size_t count)
159 {
160         struct platform_device *ndev = to_platform_device(dev);
161         struct tegra_dc *dc = platform_get_drvdata(ndev);
162         unsigned long val = 0;
163
164         if (!dc->enabled) {
165                 dev_err(&dc->ndev->dev, "%s: DC not enabled.\n", __func__);
166                 return -EFAULT;
167         }
168
169         if (strict_strtoul(buf, 10, &val) < 0)
170                 return -EINVAL;
171
172         if (val == 1) {
173                 tegra_dc_enable_crc(dc);
174                 dev_dbg(&dc->ndev->dev, "crc is enabled.\n");
175         } else if (val == 0) {
176                 tegra_dc_disable_crc(dc);
177                 dev_dbg(&dc->ndev->dev, "crc is disabled.\n");
178         } else
179                 dev_err(&dc->ndev->dev, "Invalid input.\n");
180
181         return count;
182 }
183 static DEVICE_ATTR(crc_checksum_latched, S_IRUGO|S_IWUSR,
184                 crc_checksum_latched_show, crc_checksum_latched_store);
185
186 #define ORIENTATION_PORTRAIT    "portrait"
187 #define ORIENTATION_LANDSCAPE   "landscape"
188
189 static ssize_t orientation_3d_show(struct device *dev,
190         struct device_attribute *attr, char *buf)
191 {
192         struct platform_device *ndev = to_platform_device(dev);
193         struct tegra_dc *dc = platform_get_drvdata(ndev);
194         struct tegra_dc_out *dc_out = dc->out;
195         const char *orientation;
196         switch (dc_out->stereo->orientation) {
197         case TEGRA_DC_STEREO_LANDSCAPE:
198                 orientation = ORIENTATION_LANDSCAPE;
199                 break;
200         case TEGRA_DC_STEREO_PORTRAIT:
201                 orientation = ORIENTATION_PORTRAIT;
202                 break;
203         default:
204                 pr_err("Invalid value is stored for stereo_orientation.\n");
205                 return -EINVAL;
206         }
207         return snprintf(buf, PAGE_SIZE, "%s\n", orientation);
208 }
209
210 static ssize_t orientation_3d_store(struct device *dev,
211         struct device_attribute *attr, const char *buf, size_t cnt)
212 {
213         struct platform_device *ndev = to_platform_device(dev);
214         struct tegra_dc *dc = platform_get_drvdata(ndev);
215         struct tegra_dc_out *dc_out = dc->out;
216         struct tegra_stereo_out *stereo = dc_out->stereo;
217         int orientation;
218
219         if (0 == strncmp(buf, ORIENTATION_PORTRAIT,
220                         min(cnt, ARRAY_SIZE(ORIENTATION_PORTRAIT) - 1))) {
221                 orientation = TEGRA_DC_STEREO_PORTRAIT;
222         } else if (0 == strncmp(buf, ORIENTATION_LANDSCAPE,
223                         min(cnt, ARRAY_SIZE(ORIENTATION_LANDSCAPE) - 1))) {
224                 orientation = TEGRA_DC_STEREO_LANDSCAPE;
225         } else {
226                 pr_err("Invalid property value for stereo_orientation.\n");
227                 return -EINVAL;
228         }
229         stereo->orientation = orientation;
230         stereo->set_orientation(orientation);
231         return cnt;
232 }
233
234 static DEVICE_ATTR(stereo_orientation,
235         S_IRUGO|S_IWUSR, orientation_3d_show, orientation_3d_store);
236
237 #define MODE_2D         "2d"
238 #define MODE_3D         "3d"
239
240 static ssize_t mode_3d_show(struct device *dev,
241         struct device_attribute *attr, char *buf)
242 {
243         struct platform_device *ndev = to_platform_device(dev);
244         struct tegra_dc *dc = platform_get_drvdata(ndev);
245         struct tegra_dc_out *dc_out = dc->out;
246         const char *mode;
247         switch (dc_out->stereo->mode_2d_3d) {
248         case TEGRA_DC_STEREO_MODE_2D:
249                 mode = MODE_2D;
250                 break;
251         case TEGRA_DC_STEREO_MODE_3D:
252                 mode = MODE_3D;
253                 break;
254         default:
255                 pr_err("Invalid value is stored for stereo_mode.\n");
256                 return -EINVAL;
257         }
258         return snprintf(buf, PAGE_SIZE, "%s\n", mode);
259 }
260
261 static ssize_t mode_3d_store(struct device *dev,
262         struct device_attribute *attr, const char *buf, size_t cnt)
263 {
264         struct platform_device *ndev = to_platform_device(dev);
265         struct tegra_dc *dc = platform_get_drvdata(ndev);
266         struct tegra_dc_out *dc_out = dc->out;
267         struct tegra_stereo_out *stereo = dc_out->stereo;
268         int mode;
269
270         if (0 == strncmp(buf, MODE_2D, min(cnt, ARRAY_SIZE(MODE_2D) - 1))) {
271                 mode = TEGRA_DC_STEREO_MODE_2D;
272         } else if (0 == strncmp(buf, MODE_3D,
273                         min(cnt, ARRAY_SIZE(MODE_3D) - 1))) {
274                 mode = TEGRA_DC_STEREO_MODE_3D;
275         } else {
276                 pr_err("Invalid property value for stereo_mode.\n");
277                 return -EINVAL;
278         }
279         stereo->mode_2d_3d = mode;
280         stereo->set_mode(mode);
281         return cnt;
282 }
283
284 static DEVICE_ATTR(stereo_mode,
285         S_IRUGO|S_IWUSR, mode_3d_show, mode_3d_store);
286
287 static ssize_t colorbar_show(struct device *device,
288         struct device_attribute *attr, char *buf)
289 {
290         int refresh_rate;
291         struct platform_device *ndev = to_platform_device(device);
292         struct tegra_dc *dc = platform_get_drvdata(ndev);
293
294         refresh_rate = tegra_fb_get_mode(dc);
295         return snprintf(buf, PAGE_SIZE, "%d\n", refresh_rate);
296 }
297
298 #define WIDTH 1920
299 #define HEIGHT 1200
300
301 static ssize_t colorbar_store(struct device *dev,
302         struct device_attribute *attr, const char *buf, size_t count)
303 {
304         struct platform_device *ndev = to_platform_device(dev);
305         struct tegra_dc *dc = platform_get_drvdata(ndev);
306
307         struct nvmap_client     *test_nvmap;
308         struct nvmap_handle_ref *win;
309         int i, j;
310         phys_addr_t phys_addr;
311         u8* win_ptr;
312         u32 *ptr;
313         u32 val;
314
315         printk("===== test is started ====\n");
316         test_nvmap = nvmap_create_client(nvmap_dev, "wint_test");
317         win = nvmap_alloc(test_nvmap, WIDTH*HEIGHT*4*2, 32, NVMAP_HANDLE_WRITE_COMBINE, 0);
318         phys_addr = nvmap_pin(test_nvmap, win);
319
320         win_ptr = nvmap_mmap(win);
321
322         ptr = (u32*) win_ptr;
323         for(i = 0; i < HEIGHT / 4; i++)
324                 for(j = 0; j < WIDTH; j++)
325                         *(ptr++) = 0xff0000ff;
326         for(i = 0; i < HEIGHT / 4; i++)
327                 for(j = 0; j < WIDTH; j++)
328                         *(ptr++) = 0xff00ff00;
329         for(i = 0; i < HEIGHT / 4; i++)
330                 for(j = 0; j < WIDTH; j++)
331                         *(ptr++) = 0xffff0000;
332         for(i = 0; i < HEIGHT / 4; i++)
333                 for(j = 0; j < WIDTH; j++)
334                         *(ptr++) = 0xff0000ff;
335
336
337         tegra_dc_writel(dc, WINDOW_A_SELECT,
338                         DC_CMD_DISPLAY_WINDOW_HEADER);
339
340         val = WIN_ENABLE;
341         tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
342         tegra_dc_writel(dc, 0xd, DC_WIN_COLOR_DEPTH);
343
344         tegra_dc_writel(dc,
345                 V_POSITION(0) | H_POSITION(0),
346                 DC_WIN_POSITION);
347         tegra_dc_writel(dc,
348                 V_SIZE(1200) | H_SIZE(1920),
349                 DC_WIN_SIZE);
350
351         tegra_dc_writel(dc,
352                         V_PRESCALED_SIZE(1200) |
353                         H_PRESCALED_SIZE(1920 * 4),
354                         DC_WIN_PRESCALED_SIZE);
355
356                 tegra_dc_writel(dc, 0x10001000, DC_WIN_DDA_INCREMENT);
357                 tegra_dc_writel(dc, 0, DC_WIN_H_INITIAL_DDA);
358                 tegra_dc_writel(dc, 0, DC_WIN_V_INITIAL_DDA);
359
360         tegra_dc_writel(dc, phys_addr, DC_WINBUF_START_ADDR);
361
362         tegra_dc_writel(dc, 1920*4, DC_WIN_LINE_STRIDE);
363
364         tegra_dc_writel(dc, 0, DC_WINBUF_ADDR_H_OFFSET);
365         tegra_dc_writel(dc, 0, DC_WINBUF_ADDR_V_OFFSET);
366
367         tegra_dc_writel(dc,
368                                 DC_WIN_BUFFER_ADDR_MODE_LINEAR |
369                                 DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV,
370                                 DC_WIN_BUFFER_ADDR_MODE);
371         tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN);
372
373         tegra_dc_writel(dc, WIN_A_UPDATE | GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
374         tegra_dc_writel(dc, WIN_A_ACT_REQ | GENERAL_ACT_REQ , DC_CMD_STATE_CONTROL);
375
376         return count;
377 }
378
379 static DEVICE_ATTR(colorbar, S_IRUGO|S_IWUSR, colorbar_show, colorbar_store);
380
381 static ssize_t nvdps_show(struct device *device,
382         struct device_attribute *attr, char *buf)
383 {
384         int refresh_rate;
385         struct platform_device *ndev = to_platform_device(device);
386         struct tegra_dc *dc = platform_get_drvdata(ndev);
387
388         refresh_rate = tegra_fb_get_mode(dc);
389         return snprintf(buf, PAGE_SIZE, "%d\n", refresh_rate);
390 }
391
392
393 static ssize_t nvdps_store(struct device *dev,
394         struct device_attribute *attr, const char *buf, size_t count)
395 {
396         struct platform_device *ndev = to_platform_device(dev);
397         struct tegra_dc *dc = platform_get_drvdata(ndev);
398         int refresh_rate;
399         int e;
400
401         e = kstrtoint(buf, 10, &refresh_rate);
402         if (e)
403                 return e;
404         e = tegra_fb_set_mode(dc, refresh_rate);
405
406         return count;
407 }
408
409 static DEVICE_ATTR(nvdps, S_IRUGO|S_IWUSR, nvdps_show, nvdps_store);
410
411 #ifdef CONFIG_TEGRA_DC_CMU
412 static ssize_t cmu_enable_store(struct device *dev,
413         struct device_attribute *attr, const char *buf, size_t count)
414 {
415         int val;
416         int e;
417         struct platform_device *ndev = to_platform_device(dev);
418         struct tegra_dc *dc = platform_get_drvdata(ndev);
419
420         e = kstrtoint(buf, 10, &val);
421         if (e)
422                 return e;
423
424         tegra_dc_cmu_enable(dc, val);
425
426         return count;
427 }
428
429 static ssize_t cmu_enable_show(struct device *dev,
430         struct device_attribute *attr, char *buf)
431 {
432         struct platform_device *ndev = to_platform_device(dev);
433         struct tegra_dc *dc = platform_get_drvdata(ndev);
434
435         return snprintf(buf, PAGE_SIZE, "%d\n", dc->pdata->cmu_enable);
436 }
437
438 static DEVICE_ATTR(cmu_enable,
439                 S_IRUGO|S_IWUSR, cmu_enable_show, cmu_enable_store);
440 #endif
441 static ssize_t smart_panel_show(struct device *device,
442         struct device_attribute *attr, char  *buf)
443 {
444         return snprintf(buf, PAGE_SIZE, "1\n");
445 }
446
447 static DEVICE_ATTR(smart_panel, S_IRUGO, smart_panel_show, NULL);
448
449 void __devexit tegra_dc_remove_sysfs(struct device *dev)
450 {
451         struct platform_device *ndev = to_platform_device(dev);
452         struct tegra_dc *dc = platform_get_drvdata(ndev);
453         struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
454
455         device_remove_file(dev, &dev_attr_mode);
456         device_remove_file(dev, &dev_attr_nvdps);
457         device_remove_file(dev, &dev_attr_enable);
458         device_remove_file(dev, &dev_attr_stats_enable);
459         device_remove_file(dev, &dev_attr_crc_checksum_latched);
460         device_remove_file(dev, &dev_attr_colorbar);
461 #ifdef CONFIG_TEGRA_DC_CMU
462         device_remove_file(dev, &dev_attr_cmu_enable);
463 #endif
464
465         if (dc->out->stereo) {
466                 device_remove_file(dev, &dev_attr_stereo_orientation);
467                 device_remove_file(dev, &dev_attr_stereo_mode);
468         }
469
470         if (sd_settings)
471                 nvsd_remove_sysfs(dev);
472
473         if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
474                 device_remove_file(dev, &dev_attr_smart_panel);
475 }
476
477 void tegra_dc_create_sysfs(struct device *dev)
478 {
479         struct platform_device *ndev = to_platform_device(dev);
480         struct tegra_dc *dc = platform_get_drvdata(ndev);
481         struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
482         int error = 0;
483
484         error |= device_create_file(dev, &dev_attr_mode);
485         error |= device_create_file(dev, &dev_attr_nvdps);
486         error |= device_create_file(dev, &dev_attr_enable);
487         error |= device_create_file(dev, &dev_attr_stats_enable);
488         error |= device_create_file(dev, &dev_attr_crc_checksum_latched);
489         error |= device_create_file(dev, &dev_attr_colorbar);
490 #ifdef CONFIG_TEGRA_DC_CMU
491         error |= device_create_file(dev, &dev_attr_cmu_enable);
492 #endif
493
494         if (dc->out->stereo) {
495                 error |= device_create_file(dev, &dev_attr_stereo_orientation);
496                 error |= device_create_file(dev, &dev_attr_stereo_mode);
497         }
498
499         if (sd_settings)
500                 error |= nvsd_create_sysfs(dev);
501
502         if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
503                 error |= device_create_file(dev, &dev_attr_smart_panel);
504
505         if (error)
506                 dev_err(&ndev->dev, "Failed to create sysfs attributes!\n");
507 }