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