]> Pileus Git - ~andy/linux/blob - drivers/video/omap2/dss/manager-sysfs.c
OMAPDSS: alloc dssdevs dynamically
[~andy/linux] / drivers / video / omap2 / dss / manager-sysfs.c
1 /*
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
34 static 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
39 static 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
45 static 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
92 put_device:
93         if (dssdev)
94                 omap_dss_put_device(dssdev);
95
96         return r ? r : size;
97 }
98
99 static 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
109 static 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
135 static const char *trans_key_type_str[] = {
136         "gfx-destination",
137         "video-source",
138 };
139
140 static 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
154 static 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
185 static 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
195 static 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
221 static 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
231 static 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
257 static 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
270 static 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
299 static 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
309 static 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
341 static 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
361 static 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
402 struct 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
412 static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
413 static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
414                 manager_display_show, manager_display_store);
415 static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
416                 manager_default_color_show, manager_default_color_store);
417 static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
418                 manager_trans_key_type_show, manager_trans_key_type_store);
419 static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
420                 manager_trans_key_value_show, manager_trans_key_value_store);
421 static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
422                 manager_trans_key_enabled_show,
423                 manager_trans_key_enabled_store);
424 static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
425                 manager_alpha_blending_enabled_show,
426                 manager_alpha_blending_enabled_store);
427 static MANAGER_ATTR(cpr_enable, S_IRUGO|S_IWUSR,
428                 manager_cpr_enable_show,
429                 manager_cpr_enable_store);
430 static MANAGER_ATTR(cpr_coef, S_IRUGO|S_IWUSR,
431                 manager_cpr_coef_show,
432                 manager_cpr_coef_store);
433
434
435 static 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
448 static 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
463 static 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
478 static const struct sysfs_ops manager_sysfs_ops = {
479         .show = manager_attr_show,
480         .store = manager_attr_store,
481 };
482
483 static struct kobj_type manager_ktype = {
484         .sysfs_ops = &manager_sysfs_ops,
485         .default_attrs = manager_sysfs_attrs,
486 };
487
488 int 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
495 void dss_manager_kobj_uninit(struct omap_overlay_manager *mgr)
496 {
497         kobject_del(&mgr->kobj);
498         kobject_put(&mgr->kobj);
499 }