Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
overlay-sysfs.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2009 Nokia Corporation
3  * Author: Tomi Valkeinen <[email protected]>
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 "OVERLAY"
22 
23 #include <linux/module.h>
24 #include <linux/err.h>
25 #include <linux/sysfs.h>
26 #include <linux/kobject.h>
27 #include <linux/platform_device.h>
28 
29 #include <video/omapdss.h>
30 
31 #include "dss.h"
32 #include "dss_features.h"
33 
34 static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
35 {
36  return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
37 }
38 
39 static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf)
40 {
41  return snprintf(buf, PAGE_SIZE, "%s\n",
42  ovl->manager ? ovl->manager->name : "<none>");
43 }
44 
45 static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf,
46  size_t size)
47 {
48  int i, r;
49  struct omap_overlay_manager *mgr = NULL;
50  struct omap_overlay_manager *old_mgr;
51  int len = size;
52 
53  if (buf[size-1] == '\n')
54  --len;
55 
56  if (len > 0) {
57  for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
59 
60  if (sysfs_streq(buf, mgr->name))
61  break;
62 
63  mgr = NULL;
64  }
65  }
66 
67  if (len > 0 && mgr == NULL)
68  return -EINVAL;
69 
70  if (mgr)
71  DSSDBG("manager %s found\n", mgr->name);
72 
73  if (mgr == ovl->manager)
74  return size;
75 
76  old_mgr = ovl->manager;
77 
78  r = dispc_runtime_get();
79  if (r)
80  return r;
81 
82  /* detach old manager */
83  if (old_mgr) {
84  r = ovl->unset_manager(ovl);
85  if (r) {
86  DSSERR("detach failed\n");
87  goto err;
88  }
89 
90  r = old_mgr->apply(old_mgr);
91  if (r)
92  goto err;
93  }
94 
95  if (mgr) {
96  r = ovl->set_manager(ovl, mgr);
97  if (r) {
98  DSSERR("Failed to attach overlay\n");
99  goto err;
100  }
101 
102  r = mgr->apply(mgr);
103  if (r)
104  goto err;
105  }
106 
108 
109  return size;
110 
111 err:
113  return r;
114 }
115 
116 static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
117 {
118  struct omap_overlay_info info;
119 
120  ovl->get_overlay_info(ovl, &info);
121 
122  return snprintf(buf, PAGE_SIZE, "%d,%d\n",
123  info.width, info.height);
124 }
125 
126 static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
127 {
128  struct omap_overlay_info info;
129 
130  ovl->get_overlay_info(ovl, &info);
131 
132  return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
133 }
134 
135 static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
136 {
137  struct omap_overlay_info info;
138 
139  ovl->get_overlay_info(ovl, &info);
140 
141  return snprintf(buf, PAGE_SIZE, "%d,%d\n",
142  info.pos_x, info.pos_y);
143 }
144 
145 static ssize_t overlay_position_store(struct omap_overlay *ovl,
146  const char *buf, size_t size)
147 {
148  int r;
149  char *last;
150  struct omap_overlay_info info;
151 
152  ovl->get_overlay_info(ovl, &info);
153 
154  info.pos_x = simple_strtoul(buf, &last, 10);
155  ++last;
156  if (last - buf >= size)
157  return -EINVAL;
158 
159  info.pos_y = simple_strtoul(last, &last, 10);
160 
161  r = ovl->set_overlay_info(ovl, &info);
162  if (r)
163  return r;
164 
165  if (ovl->manager) {
166  r = ovl->manager->apply(ovl->manager);
167  if (r)
168  return r;
169  }
170 
171  return size;
172 }
173 
174 static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
175 {
176  struct omap_overlay_info info;
177 
178  ovl->get_overlay_info(ovl, &info);
179 
180  return snprintf(buf, PAGE_SIZE, "%d,%d\n",
181  info.out_width, info.out_height);
182 }
183 
184 static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
185  const char *buf, size_t size)
186 {
187  int r;
188  char *last;
189  struct omap_overlay_info info;
190 
191  ovl->get_overlay_info(ovl, &info);
192 
193  info.out_width = simple_strtoul(buf, &last, 10);
194  ++last;
195  if (last - buf >= size)
196  return -EINVAL;
197 
198  info.out_height = simple_strtoul(last, &last, 10);
199 
200  r = ovl->set_overlay_info(ovl, &info);
201  if (r)
202  return r;
203 
204  if (ovl->manager) {
205  r = ovl->manager->apply(ovl->manager);
206  if (r)
207  return r;
208  }
209 
210  return size;
211 }
212 
213 static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
214 {
215  return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
216 }
217 
218 static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
219  size_t size)
220 {
221  int r;
222  bool enable;
223 
224  r = strtobool(buf, &enable);
225  if (r)
226  return r;
227 
228  if (enable)
229  r = ovl->enable(ovl);
230  else
231  r = ovl->disable(ovl);
232 
233  if (r)
234  return r;
235 
236  return size;
237 }
238 
239 static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
240 {
241  struct omap_overlay_info info;
242 
243  ovl->get_overlay_info(ovl, &info);
244 
245  return snprintf(buf, PAGE_SIZE, "%d\n",
246  info.global_alpha);
247 }
248 
249 static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
250  const char *buf, size_t size)
251 {
252  int r;
253  u8 alpha;
254  struct omap_overlay_info info;
255 
256  if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
257  return -ENODEV;
258 
259  r = kstrtou8(buf, 0, &alpha);
260  if (r)
261  return r;
262 
263  ovl->get_overlay_info(ovl, &info);
264 
265  info.global_alpha = alpha;
266 
267  r = ovl->set_overlay_info(ovl, &info);
268  if (r)
269  return r;
270 
271  if (ovl->manager) {
272  r = ovl->manager->apply(ovl->manager);
273  if (r)
274  return r;
275  }
276 
277  return size;
278 }
279 
280 static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
281  char *buf)
282 {
283  struct omap_overlay_info info;
284 
285  ovl->get_overlay_info(ovl, &info);
286 
287  return snprintf(buf, PAGE_SIZE, "%d\n",
288  info.pre_mult_alpha);
289 }
290 
291 static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
292  const char *buf, size_t size)
293 {
294  int r;
295  u8 alpha;
296  struct omap_overlay_info info;
297 
298  if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
299  return -ENODEV;
300 
301  r = kstrtou8(buf, 0, &alpha);
302  if (r)
303  return r;
304 
305  ovl->get_overlay_info(ovl, &info);
306 
307  info.pre_mult_alpha = alpha;
308 
309  r = ovl->set_overlay_info(ovl, &info);
310  if (r)
311  return r;
312 
313  if (ovl->manager) {
314  r = ovl->manager->apply(ovl->manager);
315  if (r)
316  return r;
317  }
318 
319  return size;
320 }
321 
322 static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
323 {
324  struct omap_overlay_info info;
325 
326  ovl->get_overlay_info(ovl, &info);
327 
328  return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
329 }
330 
331 static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
332  const char *buf, size_t size)
333 {
334  int r;
335  u8 zorder;
336  struct omap_overlay_info info;
337 
338  if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
339  return -ENODEV;
340 
341  r = kstrtou8(buf, 0, &zorder);
342  if (r)
343  return r;
344 
345  ovl->get_overlay_info(ovl, &info);
346 
347  info.zorder = zorder;
348 
349  r = ovl->set_overlay_info(ovl, &info);
350  if (r)
351  return r;
352 
353  if (ovl->manager) {
354  r = ovl->manager->apply(ovl->manager);
355  if (r)
356  return r;
357  }
358 
359  return size;
360 }
361 
363  struct attribute attr;
364  ssize_t (*show)(struct omap_overlay *, char *);
365  ssize_t (*store)(struct omap_overlay *, const char *, size_t);
366 };
367 
368 #define OVERLAY_ATTR(_name, _mode, _show, _store) \
369  struct overlay_attribute overlay_attr_##_name = \
370  __ATTR(_name, _mode, _show, _store)
371 
372 static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
374  overlay_manager_show, overlay_manager_store);
375 static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
376 static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
377 static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
378  overlay_position_show, overlay_position_store);
379 static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
380  overlay_output_size_show, overlay_output_size_store);
382  overlay_enabled_show, overlay_enabled_store);
383 static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
384  overlay_global_alpha_show, overlay_global_alpha_store);
385 static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR,
386  overlay_pre_mult_alpha_show,
387  overlay_pre_mult_alpha_store);
388 static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
389  overlay_zorder_show, overlay_zorder_store);
390 
391 static struct attribute *overlay_sysfs_attrs[] = {
392  &overlay_attr_name.attr,
393  &overlay_attr_manager.attr,
394  &overlay_attr_input_size.attr,
395  &overlay_attr_screen_width.attr,
396  &overlay_attr_position.attr,
397  &overlay_attr_output_size.attr,
398  &overlay_attr_enabled.attr,
399  &overlay_attr_global_alpha.attr,
400  &overlay_attr_pre_mult_alpha.attr,
401  &overlay_attr_zorder.attr,
402  NULL
403 };
404 
405 static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
406  char *buf)
407 {
408  struct omap_overlay *overlay;
409  struct overlay_attribute *overlay_attr;
410 
411  overlay = container_of(kobj, struct omap_overlay, kobj);
412  overlay_attr = container_of(attr, struct overlay_attribute, attr);
413 
414  if (!overlay_attr->show)
415  return -ENOENT;
416 
417  return overlay_attr->show(overlay, buf);
418 }
419 
420 static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
421  const char *buf, size_t size)
422 {
423  struct omap_overlay *overlay;
424  struct overlay_attribute *overlay_attr;
425 
426  overlay = container_of(kobj, struct omap_overlay, kobj);
427  overlay_attr = container_of(attr, struct overlay_attribute, attr);
428 
429  if (!overlay_attr->store)
430  return -ENOENT;
431 
432  return overlay_attr->store(overlay, buf, size);
433 }
434 
435 static const struct sysfs_ops overlay_sysfs_ops = {
436  .show = overlay_attr_show,
437  .store = overlay_attr_store,
438 };
439 
440 static struct kobj_type overlay_ktype = {
441  .sysfs_ops = &overlay_sysfs_ops,
442  .default_attrs = overlay_sysfs_attrs,
443 };
444 
446  struct platform_device *pdev)
447 {
448  return kobject_init_and_add(&ovl->kobj, &overlay_ktype,
449  &pdev->dev.kobj, "overlay%d", ovl->id);
450 }
451 
453 {
454  kobject_del(&ovl->kobj);
455  kobject_put(&ovl->kobj);
456 }