2 * Copyright (C) 2009 Nokia Corporation
3 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
5 * Some code and ideas taken from drivers/video/omap/ driver
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.
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
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/>.
21 #define DSS_SUBSYS_NAME "DISPLAY"
23 #include <linux/kernel.h>
24 #include <linux/module.h>
25 #include <linux/platform_device.h>
26 #include <linux/sysfs.h>
28 #include <video/omapdss.h>
31 static ssize_t
display_name_show(struct omap_dss_device
*dssdev
, char *buf
)
33 return snprintf(buf
, PAGE_SIZE
, "%s\n",
38 static ssize_t
display_enabled_show(struct omap_dss_device
*dssdev
, char *buf
)
40 return snprintf(buf
, PAGE_SIZE
, "%d\n",
41 omapdss_device_is_enabled(dssdev
));
44 static ssize_t
display_enabled_store(struct omap_dss_device
*dssdev
,
45 const char *buf
, size_t size
)
50 r
= strtobool(buf
, &enable
);
54 if (enable
== omapdss_device_is_enabled(dssdev
))
57 if (omapdss_device_is_connected(dssdev
) == false)
61 r
= dssdev
->driver
->enable(dssdev
);
65 dssdev
->driver
->disable(dssdev
);
71 static ssize_t
display_tear_show(struct omap_dss_device
*dssdev
, char *buf
)
73 return snprintf(buf
, PAGE_SIZE
, "%d\n",
74 dssdev
->driver
->get_te
?
75 dssdev
->driver
->get_te(dssdev
) : 0);
78 static ssize_t
display_tear_store(struct omap_dss_device
*dssdev
,
79 const char *buf
, size_t size
)
84 if (!dssdev
->driver
->enable_te
|| !dssdev
->driver
->get_te
)
87 r
= strtobool(buf
, &te
);
91 r
= dssdev
->driver
->enable_te(dssdev
, te
);
98 static ssize_t
display_timings_show(struct omap_dss_device
*dssdev
, char *buf
)
100 struct omap_video_timings t
;
102 if (!dssdev
->driver
->get_timings
)
105 dssdev
->driver
->get_timings(dssdev
, &t
);
107 return snprintf(buf
, PAGE_SIZE
, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
109 t
.x_res
, t
.hfp
, t
.hbp
, t
.hsw
,
110 t
.y_res
, t
.vfp
, t
.vbp
, t
.vsw
);
113 static ssize_t
display_timings_store(struct omap_dss_device
*dssdev
,
114 const char *buf
, size_t size
)
116 struct omap_video_timings t
= dssdev
->panel
.timings
;
119 if (!dssdev
->driver
->set_timings
|| !dssdev
->driver
->check_timings
)
123 #ifdef CONFIG_FB_OMAP2_DSS_VENC
124 if (strncmp("pal", buf
, 3) == 0) {
125 t
= omap_dss_pal_timings
;
127 } else if (strncmp("ntsc", buf
, 4) == 0) {
128 t
= omap_dss_ntsc_timings
;
132 if (!found
&& sscanf(buf
, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
134 &t
.x_res
, &t
.hfp
, &t
.hbp
, &t
.hsw
,
135 &t
.y_res
, &t
.vfp
, &t
.vbp
, &t
.vsw
) != 9)
138 r
= dssdev
->driver
->check_timings(dssdev
, &t
);
142 dssdev
->driver
->disable(dssdev
);
143 dssdev
->driver
->set_timings(dssdev
, &t
);
144 r
= dssdev
->driver
->enable(dssdev
);
151 static ssize_t
display_rotate_show(struct omap_dss_device
*dssdev
, char *buf
)
154 if (!dssdev
->driver
->get_rotate
)
156 rotate
= dssdev
->driver
->get_rotate(dssdev
);
157 return snprintf(buf
, PAGE_SIZE
, "%u\n", rotate
);
160 static ssize_t
display_rotate_store(struct omap_dss_device
*dssdev
,
161 const char *buf
, size_t size
)
165 if (!dssdev
->driver
->set_rotate
|| !dssdev
->driver
->get_rotate
)
168 r
= kstrtoint(buf
, 0, &rot
);
172 r
= dssdev
->driver
->set_rotate(dssdev
, rot
);
179 static ssize_t
display_mirror_show(struct omap_dss_device
*dssdev
, char *buf
)
182 if (!dssdev
->driver
->get_mirror
)
184 mirror
= dssdev
->driver
->get_mirror(dssdev
);
185 return snprintf(buf
, PAGE_SIZE
, "%u\n", mirror
);
188 static ssize_t
display_mirror_store(struct omap_dss_device
*dssdev
,
189 const char *buf
, size_t size
)
194 if (!dssdev
->driver
->set_mirror
|| !dssdev
->driver
->get_mirror
)
197 r
= strtobool(buf
, &mirror
);
201 r
= dssdev
->driver
->set_mirror(dssdev
, mirror
);
208 static ssize_t
display_wss_show(struct omap_dss_device
*dssdev
, char *buf
)
212 if (!dssdev
->driver
->get_wss
)
215 wss
= dssdev
->driver
->get_wss(dssdev
);
217 return snprintf(buf
, PAGE_SIZE
, "0x%05x\n", wss
);
220 static ssize_t
display_wss_store(struct omap_dss_device
*dssdev
,
221 const char *buf
, size_t size
)
226 if (!dssdev
->driver
->get_wss
|| !dssdev
->driver
->set_wss
)
229 r
= kstrtou32(buf
, 0, &wss
);
236 r
= dssdev
->driver
->set_wss(dssdev
, wss
);
243 struct display_attribute
{
244 struct attribute attr
;
245 ssize_t (*show
)(struct omap_dss_device
*, char *);
246 ssize_t (*store
)(struct omap_dss_device
*, const char *, size_t);
249 #define DISPLAY_ATTR(_name, _mode, _show, _store) \
250 struct display_attribute display_attr_##_name = \
251 __ATTR(_name, _mode, _show, _store)
253 static DISPLAY_ATTR(name
, S_IRUGO
, display_name_show
, NULL
);
254 static DISPLAY_ATTR(display_name
, S_IRUGO
, display_name_show
, NULL
);
255 static DISPLAY_ATTR(enabled
, S_IRUGO
|S_IWUSR
,
256 display_enabled_show
, display_enabled_store
);
257 static DISPLAY_ATTR(tear_elim
, S_IRUGO
|S_IWUSR
,
258 display_tear_show
, display_tear_store
);
259 static DISPLAY_ATTR(timings
, S_IRUGO
|S_IWUSR
,
260 display_timings_show
, display_timings_store
);
261 static DISPLAY_ATTR(rotate
, S_IRUGO
|S_IWUSR
,
262 display_rotate_show
, display_rotate_store
);
263 static DISPLAY_ATTR(mirror
, S_IRUGO
|S_IWUSR
,
264 display_mirror_show
, display_mirror_store
);
265 static DISPLAY_ATTR(wss
, S_IRUGO
|S_IWUSR
,
266 display_wss_show
, display_wss_store
);
268 static struct attribute
*display_sysfs_attrs
[] = {
269 &display_attr_name
.attr
,
270 &display_attr_display_name
.attr
,
271 &display_attr_enabled
.attr
,
272 &display_attr_tear_elim
.attr
,
273 &display_attr_timings
.attr
,
274 &display_attr_rotate
.attr
,
275 &display_attr_mirror
.attr
,
276 &display_attr_wss
.attr
,
280 static ssize_t
display_attr_show(struct kobject
*kobj
, struct attribute
*attr
,
283 struct omap_dss_device
*dssdev
;
284 struct display_attribute
*display_attr
;
286 dssdev
= container_of(kobj
, struct omap_dss_device
, kobj
);
287 display_attr
= container_of(attr
, struct display_attribute
, attr
);
289 if (!display_attr
->show
)
292 return display_attr
->show(dssdev
, buf
);
295 static ssize_t
display_attr_store(struct kobject
*kobj
, struct attribute
*attr
,
296 const char *buf
, size_t size
)
298 struct omap_dss_device
*dssdev
;
299 struct display_attribute
*display_attr
;
301 dssdev
= container_of(kobj
, struct omap_dss_device
, kobj
);
302 display_attr
= container_of(attr
, struct display_attribute
, attr
);
304 if (!display_attr
->store
)
307 return display_attr
->store(dssdev
, buf
, size
);
310 static const struct sysfs_ops display_sysfs_ops
= {
311 .show
= display_attr_show
,
312 .store
= display_attr_store
,
315 static struct kobj_type display_ktype
= {
316 .sysfs_ops
= &display_sysfs_ops
,
317 .default_attrs
= display_sysfs_attrs
,
320 int display_init_sysfs(struct platform_device
*pdev
)
322 struct omap_dss_device
*dssdev
= NULL
;
325 for_each_dss_dev(dssdev
) {
326 r
= kobject_init_and_add(&dssdev
->kobj
, &display_ktype
,
327 &pdev
->dev
.kobj
, "%s", dssdev
->alias
);
329 DSSERR("failed to create sysfs files\n");
330 omap_dss_put_device(dssdev
);
338 display_uninit_sysfs(pdev
);
343 void display_uninit_sysfs(struct platform_device
*pdev
)
345 struct omap_dss_device
*dssdev
= NULL
;
347 for_each_dss_dev(dssdev
) {
348 if (kobject_name(&dssdev
->kobj
) == NULL
)
351 kobject_del(&dssdev
->kobj
);
352 kobject_put(&dssdev
->kobj
);
354 memset(&dssdev
->kobj
, 0, sizeof(dssdev
->kobj
));