blob: 9b875fbe757e45c4abfe8b0bbb9ce013acbb7082 [file] [log] [blame]
Tomi Valkeinenf6a04922012-08-06 14:44:09 +03001/*
2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
4 *
5 * Some code and ideas taken from drivers/video/omap/ driver
6 * by Imre Deak.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License version 2 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#define DSS_SUBSYS_NAME "MANAGER"
22
23#include <linux/kernel.h>
24#include <linux/slab.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/jiffies.h>
28
29#include <video/omapdss.h>
30
31#include "dss.h"
32#include "dss_features.h"
33
34static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
35{
36 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
37}
38
39static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
40{
41 return snprintf(buf, PAGE_SIZE, "%s\n",
42 mgr->device ? mgr->device->name : "<none>");
43}
44
45static ssize_t manager_display_store(struct omap_overlay_manager *mgr,
46 const char *buf, size_t size)
47{
48 int r = 0;
49 size_t len = size;
50 struct omap_dss_device *dssdev = NULL;
51
52 int match(struct omap_dss_device *dssdev, void *data)
53 {
54 const char *str = data;
55 return sysfs_streq(dssdev->name, str);
56 }
57
58 if (buf[size-1] == '\n')
59 --len;
60
61 if (len > 0)
62 dssdev = omap_dss_find_device((void *)buf, match);
63
64 if (len > 0 && dssdev == NULL)
65 return -EINVAL;
66
67 if (dssdev)
68 DSSDBG("display %s found\n", dssdev->name);
69
70 if (mgr->device) {
71 r = mgr->unset_device(mgr);
72 if (r) {
73 DSSERR("failed to unset display\n");
74 goto put_device;
75 }
76 }
77
78 if (dssdev) {
79 r = mgr->set_device(mgr, dssdev);
80 if (r) {
81 DSSERR("failed to set manager\n");
82 goto put_device;
83 }
84
85 r = mgr->apply(mgr);
86 if (r) {
87 DSSERR("failed to apply dispc config\n");
88 goto put_device;
89 }
90 }
91
92put_device:
93 if (dssdev)
94 omap_dss_put_device(dssdev);
95
96 return r ? r : size;
97}
98
99static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
100 char *buf)
101{
102 struct omap_overlay_manager_info info;
103
104 mgr->get_manager_info(mgr, &info);
105
106 return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
107}
108
109static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
110 const char *buf, size_t size)
111{
112 struct omap_overlay_manager_info info;
113 u32 color;
114 int r;
115
116 r = kstrtouint(buf, 0, &color);
117 if (r)
118 return r;
119
120 mgr->get_manager_info(mgr, &info);
121
122 info.default_color = color;
123
124 r = mgr->set_manager_info(mgr, &info);
125 if (r)
126 return r;
127
128 r = mgr->apply(mgr);
129 if (r)
130 return r;
131
132 return size;
133}
134
135static const char *trans_key_type_str[] = {
136 "gfx-destination",
137 "video-source",
138};
139
140static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
141 char *buf)
142{
143 enum omap_dss_trans_key_type key_type;
144 struct omap_overlay_manager_info info;
145
146 mgr->get_manager_info(mgr, &info);
147
148 key_type = info.trans_key_type;
149 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
150
151 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
152}
153
154static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
155 const char *buf, size_t size)
156{
157 enum omap_dss_trans_key_type key_type;
158 struct omap_overlay_manager_info info;
159 int r;
160
161 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
162 key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
163 if (sysfs_streq(buf, trans_key_type_str[key_type]))
164 break;
165 }
166
167 if (key_type == ARRAY_SIZE(trans_key_type_str))
168 return -EINVAL;
169
170 mgr->get_manager_info(mgr, &info);
171
172 info.trans_key_type = key_type;
173
174 r = mgr->set_manager_info(mgr, &info);
175 if (r)
176 return r;
177
178 r = mgr->apply(mgr);
179 if (r)
180 return r;
181
182 return size;
183}
184
185static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
186 char *buf)
187{
188 struct omap_overlay_manager_info info;
189
190 mgr->get_manager_info(mgr, &info);
191
192 return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
193}
194
195static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
196 const char *buf, size_t size)
197{
198 struct omap_overlay_manager_info info;
199 u32 key_value;
200 int r;
201
202 r = kstrtouint(buf, 0, &key_value);
203 if (r)
204 return r;
205
206 mgr->get_manager_info(mgr, &info);
207
208 info.trans_key = key_value;
209
210 r = mgr->set_manager_info(mgr, &info);
211 if (r)
212 return r;
213
214 r = mgr->apply(mgr);
215 if (r)
216 return r;
217
218 return size;
219}
220
221static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
222 char *buf)
223{
224 struct omap_overlay_manager_info info;
225
226 mgr->get_manager_info(mgr, &info);
227
228 return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
229}
230
231static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
232 const char *buf, size_t size)
233{
234 struct omap_overlay_manager_info info;
235 bool enable;
236 int r;
237
238 r = strtobool(buf, &enable);
239 if (r)
240 return r;
241
242 mgr->get_manager_info(mgr, &info);
243
244 info.trans_enabled = enable;
245
246 r = mgr->set_manager_info(mgr, &info);
247 if (r)
248 return r;
249
250 r = mgr->apply(mgr);
251 if (r)
252 return r;
253
254 return size;
255}
256
257static ssize_t manager_alpha_blending_enabled_show(
258 struct omap_overlay_manager *mgr, char *buf)
259{
260 struct omap_overlay_manager_info info;
261
262 mgr->get_manager_info(mgr, &info);
263
264 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
265
266 return snprintf(buf, PAGE_SIZE, "%d\n",
267 info.partial_alpha_enabled);
268}
269
270static ssize_t manager_alpha_blending_enabled_store(
271 struct omap_overlay_manager *mgr,
272 const char *buf, size_t size)
273{
274 struct omap_overlay_manager_info info;
275 bool enable;
276 int r;
277
278 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
279
280 r = strtobool(buf, &enable);
281 if (r)
282 return r;
283
284 mgr->get_manager_info(mgr, &info);
285
286 info.partial_alpha_enabled = enable;
287
288 r = mgr->set_manager_info(mgr, &info);
289 if (r)
290 return r;
291
292 r = mgr->apply(mgr);
293 if (r)
294 return r;
295
296 return size;
297}
298
299static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
300 char *buf)
301{
302 struct omap_overlay_manager_info info;
303
304 mgr->get_manager_info(mgr, &info);
305
306 return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
307}
308
309static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
310 const char *buf, size_t size)
311{
312 struct omap_overlay_manager_info info;
313 int r;
314 bool enable;
315
316 if (!dss_has_feature(FEAT_CPR))
317 return -ENODEV;
318
319 r = strtobool(buf, &enable);
320 if (r)
321 return r;
322
323 mgr->get_manager_info(mgr, &info);
324
325 if (info.cpr_enable == enable)
326 return size;
327
328 info.cpr_enable = enable;
329
330 r = mgr->set_manager_info(mgr, &info);
331 if (r)
332 return r;
333
334 r = mgr->apply(mgr);
335 if (r)
336 return r;
337
338 return size;
339}
340
341static ssize_t manager_cpr_coef_show(struct omap_overlay_manager *mgr,
342 char *buf)
343{
344 struct omap_overlay_manager_info info;
345
346 mgr->get_manager_info(mgr, &info);
347
348 return snprintf(buf, PAGE_SIZE,
349 "%d %d %d %d %d %d %d %d %d\n",
350 info.cpr_coefs.rr,
351 info.cpr_coefs.rg,
352 info.cpr_coefs.rb,
353 info.cpr_coefs.gr,
354 info.cpr_coefs.gg,
355 info.cpr_coefs.gb,
356 info.cpr_coefs.br,
357 info.cpr_coefs.bg,
358 info.cpr_coefs.bb);
359}
360
361static ssize_t manager_cpr_coef_store(struct omap_overlay_manager *mgr,
362 const char *buf, size_t size)
363{
364 struct omap_overlay_manager_info info;
365 struct omap_dss_cpr_coefs coefs;
366 int r, i;
367 s16 *arr;
368
369 if (!dss_has_feature(FEAT_CPR))
370 return -ENODEV;
371
372 if (sscanf(buf, "%hd %hd %hd %hd %hd %hd %hd %hd %hd",
373 &coefs.rr, &coefs.rg, &coefs.rb,
374 &coefs.gr, &coefs.gg, &coefs.gb,
375 &coefs.br, &coefs.bg, &coefs.bb) != 9)
376 return -EINVAL;
377
378 arr = (s16[]){ coefs.rr, coefs.rg, coefs.rb,
379 coefs.gr, coefs.gg, coefs.gb,
380 coefs.br, coefs.bg, coefs.bb };
381
382 for (i = 0; i < 9; ++i) {
383 if (arr[i] < -512 || arr[i] > 511)
384 return -EINVAL;
385 }
386
387 mgr->get_manager_info(mgr, &info);
388
389 info.cpr_coefs = coefs;
390
391 r = mgr->set_manager_info(mgr, &info);
392 if (r)
393 return r;
394
395 r = mgr->apply(mgr);
396 if (r)
397 return r;
398
399 return size;
400}
401
402struct manager_attribute {
403 struct attribute attr;
404 ssize_t (*show)(struct omap_overlay_manager *, char *);
405 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
406};
407
408#define MANAGER_ATTR(_name, _mode, _show, _store) \
409 struct manager_attribute manager_attr_##_name = \
410 __ATTR(_name, _mode, _show, _store)
411
412static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
413static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
414 manager_display_show, manager_display_store);
415static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
416 manager_default_color_show, manager_default_color_store);
417static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
418 manager_trans_key_type_show, manager_trans_key_type_store);
419static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
420 manager_trans_key_value_show, manager_trans_key_value_store);
421static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
422 manager_trans_key_enabled_show,
423 manager_trans_key_enabled_store);
424static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
425 manager_alpha_blending_enabled_show,
426 manager_alpha_blending_enabled_store);
427static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
428 manager_cpr_enable_show,
429 manager_cpr_enable_store);
430static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
431 manager_cpr_coef_show,
432 manager_cpr_coef_store);
433
434
435static struct attribute *manager_sysfs_attrs[] = {
436 &manager_attr_name.attr,
437 &manager_attr_display.attr,
438 &manager_attr_default_color.attr,
439 &manager_attr_trans_key_type.attr,
440 &manager_attr_trans_key_value.attr,
441 &manager_attr_trans_key_enabled.attr,
442 &manager_attr_alpha_blending_enabled.attr,
443 &manager_attr_cpr_enable.attr,
444 &manager_attr_cpr_coef.attr,
445 NULL
446};
447
448static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
449 char *buf)
450{
451 struct omap_overlay_manager *manager;
452 struct manager_attribute *manager_attr;
453
454 manager = container_of(kobj, struct omap_overlay_manager, kobj);
455 manager_attr = container_of(attr, struct manager_attribute, attr);
456
457 if (!manager_attr->show)
458 return -ENOENT;
459
460 return manager_attr->show(manager, buf);
461}
462
463static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
464 const char *buf, size_t size)
465{
466 struct omap_overlay_manager *manager;
467 struct manager_attribute *manager_attr;
468
469 manager = container_of(kobj, struct omap_overlay_manager, kobj);
470 manager_attr = container_of(attr, struct manager_attribute, attr);
471
472 if (!manager_attr->store)
473 return -ENOENT;
474
475 return manager_attr->store(manager, buf, size);
476}
477
478static const struct sysfs_ops manager_sysfs_ops = {
479 .show = manager_attr_show,
480 .store = manager_attr_store,
481};
482
483static struct kobj_type manager_ktype = {
484 .sysfs_ops = &manager_sysfs_ops,
485 .default_attrs = manager_sysfs_attrs,
486};
487
488int dss_manager_kobj_init(struct omap_overlay_manager *mgr,
489 struct platform_device *pdev)
490{
491 return kobject_init_and_add(&mgr->kobj, &manager_ktype,
492 &pdev->dev.kobj, "manager%d", mgr->id);
493}
494
495void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
496{
497 kobject_del(&mgr->kobj);
498 kobject_put(&mgr->kobj);
499}