2 * linux/drivers/video/omap2/dss/manager.c
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
7 * Some code and ideas taken from drivers/video/omap/ driver
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published by
12 * the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * You should have received a copy of the GNU General Public License along with
20 * this program. If not, see <http://www.gnu.org/licenses/>.
23 #define DSS_SUBSYS_NAME "MANAGER"
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/platform_device.h>
29 #include <mach/display.h>
33 static int num_managers;
34 static struct list_head manager_list;
36 static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
38 return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
41 static ssize_t manager_display_show(struct omap_overlay_manager *mgr, char *buf)
43 return snprintf(buf, PAGE_SIZE, "%s\n",
44 mgr->display ? mgr->display->name : "<none>");
47 static ssize_t manager_display_store(struct omap_overlay_manager *mgr, const char *buf, size_t size)
51 struct omap_display *display = NULL;
53 if (buf[size-1] == '\n')
57 for (i = 0; i < omap_dss_get_num_displays(); ++i) {
58 display = dss_get_display(i);
60 if (strncmp(buf, display->name, len) == 0)
67 if (len > 0 && display == NULL)
71 DSSDBG("display %s found\n", display->name);
74 r = mgr->unset_display(mgr);
76 DSSERR("failed to unset display\n");
82 r = mgr->set_display(mgr, display);
84 DSSERR("failed to set manager\n");
90 DSSERR("failed to apply dispc config\n");
98 static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
101 return snprintf(buf, PAGE_SIZE, "%d",
102 mgr->get_default_color(mgr));
105 static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
106 const char *buf, size_t size)
110 if (sscanf(buf, "%d", &default_color) != 1)
112 dispc_set_default_color(mgr->id, default_color);
117 static const char *color_key_type_str[] = {
122 static ssize_t manager_color_key_type_show(struct omap_overlay_manager *mgr,
125 enum omap_dss_color_key_type key_type;
127 mgr->get_trans_key_type_and_value(mgr, &key_type, NULL);
128 BUG_ON(key_type >= ARRAY_SIZE(color_key_type_str));
130 return snprintf(buf, PAGE_SIZE, "%s\n", color_key_type_str[key_type]);
133 static ssize_t manager_color_key_type_store(struct omap_overlay_manager *mgr,
134 const char *buf, size_t size)
136 enum omap_dss_color_key_type key_type;
139 for (key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
140 key_type < ARRAY_SIZE(color_key_type_str); key_type++) {
141 if (sysfs_streq(buf, color_key_type_str[key_type]))
144 if (key_type == ARRAY_SIZE(color_key_type_str))
146 mgr->get_trans_key_type_and_value(mgr, NULL, &key_value);
147 mgr->set_trans_key_type_and_value(mgr, key_type, key_value);
152 static ssize_t manager_color_key_value_show(struct omap_overlay_manager *mgr,
157 mgr->get_trans_key_type_and_value(mgr, NULL, &key_value);
159 return snprintf(buf, PAGE_SIZE, "%d\n", key_value);
162 static ssize_t manager_color_key_value_store(struct omap_overlay_manager *mgr,
163 const char *buf, size_t size)
165 enum omap_dss_color_key_type key_type;
168 if (sscanf(buf, "%d", &key_value) != 1)
170 mgr->get_trans_key_type_and_value(mgr, &key_type, NULL);
171 mgr->set_trans_key_type_and_value(mgr, key_type, key_value);
176 static ssize_t manager_color_key_enabled_show(struct omap_overlay_manager *mgr,
179 return snprintf(buf, PAGE_SIZE, "%d\n",
180 mgr->get_trans_key_status(mgr));
183 static ssize_t manager_color_key_enabled_store(struct omap_overlay_manager *mgr,
184 const char *buf, size_t size)
188 if (sscanf(buf, "%d", &enable) != 1)
191 mgr->enable_trans_key(mgr, enable);
197 struct manager_attribute {
198 struct attribute attr;
199 ssize_t (*show)(struct omap_overlay_manager *, char *);
200 ssize_t (*store)(struct omap_overlay_manager *, const char *, size_t);
203 #define MANAGER_ATTR(_name, _mode, _show, _store) \
204 struct manager_attribute manager_attr_##_name = \
205 __ATTR(_name, _mode, _show, _store)
207 static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
208 static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
209 manager_display_show, manager_display_store);
210 static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
211 manager_default_color_show, manager_default_color_store);
212 static MANAGER_ATTR(color_key_type, S_IRUGO|S_IWUSR,
213 manager_color_key_type_show, manager_color_key_type_store);
214 static MANAGER_ATTR(color_key_value, S_IRUGO|S_IWUSR,
215 manager_color_key_value_show, manager_color_key_value_store);
216 static MANAGER_ATTR(color_key_enabled, S_IRUGO|S_IWUSR,
217 manager_color_key_enabled_show, manager_color_key_enabled_store);
219 static struct attribute *manager_sysfs_attrs[] = {
220 &manager_attr_name.attr,
221 &manager_attr_display.attr,
222 &manager_attr_default_color.attr,
223 &manager_attr_color_key_type.attr,
224 &manager_attr_color_key_value.attr,
225 &manager_attr_color_key_enabled.attr,
229 static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
231 struct omap_overlay_manager *manager;
232 struct manager_attribute *manager_attr;
234 manager = container_of(kobj, struct omap_overlay_manager, kobj);
235 manager_attr = container_of(attr, struct manager_attribute, attr);
237 if (!manager_attr->show)
240 return manager_attr->show(manager, buf);
243 static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
244 const char *buf, size_t size)
246 struct omap_overlay_manager *manager;
247 struct manager_attribute *manager_attr;
249 manager = container_of(kobj, struct omap_overlay_manager, kobj);
250 manager_attr = container_of(attr, struct manager_attribute, attr);
252 if (!manager_attr->store)
255 return manager_attr->store(manager, buf, size);
258 static struct sysfs_ops manager_sysfs_ops = {
259 .show = manager_attr_show,
260 .store = manager_attr_store,
263 static struct kobj_type manager_ktype = {
264 .sysfs_ops = &manager_sysfs_ops,
265 .default_attrs = manager_sysfs_attrs,
268 static int omap_dss_set_display(struct omap_overlay_manager *mgr,
269 struct omap_display *display)
274 if (display->manager) {
275 DSSERR("display '%s' already has a manager '%s'\n",
276 display->name, display->manager->name);
280 if ((mgr->supported_displays & display->type) == 0) {
281 DSSERR("display '%s' does not support manager '%s'\n",
282 display->name, mgr->name);
286 for (i = 0; i < mgr->num_overlays; i++) {
287 struct omap_overlay *ovl = mgr->overlays[i];
289 if (ovl->manager != mgr || !ovl->info.enabled)
292 r = dss_check_overlay(ovl, display);
297 display->manager = mgr;
298 mgr->display = display;
303 static int omap_dss_unset_display(struct omap_overlay_manager *mgr)
306 DSSERR("failed to unset display, display not set.\n");
310 mgr->display->manager = NULL;
317 static int overlay_enabled(struct omap_overlay *ovl)
319 return ovl->info.enabled && ovl->manager && ovl->manager->display;
322 /* We apply settings to both managers here so that we can use optimizations
323 * like fifomerge. Shadow registers can be changed first and the non-shadowed
324 * should be changed last, at the same time with GO */
325 static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
329 enum omap_dss_update_mode mode;
330 struct omap_display *display;
331 struct omap_overlay *ovl;
335 int num_planes_enabled = 0;
337 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
339 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
341 /* Configure normal overlay parameters and disable unused overlays */
342 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
343 ovl = omap_dss_get_overlay(i);
345 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
348 if (!overlay_enabled(ovl)) {
349 dispc_enable_plane(ovl->id, 0);
353 display = ovl->manager->display;
355 if (dss_check_overlay(ovl, display)) {
356 dispc_enable_plane(ovl->id, 0);
360 ++num_planes_enabled;
362 /* On a manual update display, in manual update mode, update()
363 * handles configuring planes */
364 mode = OMAP_DSS_UPDATE_AUTO;
365 if (display->get_update_mode)
366 mode = display->get_update_mode(mgr->display);
368 if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
369 mode != OMAP_DSS_UPDATE_AUTO)
372 if (display->type == OMAP_DISPLAY_TYPE_VENC)
375 if (ovl->info.out_width == 0)
376 outw = ovl->info.width;
378 outw = ovl->info.out_width;
380 if (ovl->info.out_height == 0)
381 outh = ovl->info.height;
383 outh = ovl->info.out_height;
385 r = dispc_setup_plane(ovl->id, ovl->manager->id,
387 ovl->info.screen_width,
394 ovl->info.color_mode,
396 ovl->info.rotation_type,
401 DSSERR("dispc_setup_plane failed for ovl %d\n",
403 dispc_enable_plane(ovl->id, 0);
407 dispc_enable_plane(ovl->id, 1);
410 /* Enable fifo merge if possible */
411 dispc_enable_fifomerge(num_planes_enabled == 1);
413 /* Go through overlays again. This time we configure fifos. We have to
414 * do this after enabling/disabling fifomerge so that we have correct
415 * knowledge of fifo sizes */
416 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
417 ovl = omap_dss_get_overlay(i);
419 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC))
422 if (!overlay_enabled(ovl)) {
426 ovl->manager->display->configure_overlay(ovl);
429 /* Issue GO for managers */
430 list_for_each_entry(mgr, &manager_list, list) {
431 if (!(mgr->caps & OMAP_DSS_OVL_MGR_CAP_DISPC))
434 display = mgr->display;
439 /* We don't need GO with manual update display. LCD iface will
440 * always be turned off after frame, and new settings will
441 * be taken in to use at next update */
442 if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
448 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
453 static void omap_dss_mgr_set_def_color(struct omap_overlay_manager *mgr,
456 dispc_set_default_color(mgr->id, color);
459 static void omap_dss_mgr_set_trans_key_type_and_value(
460 struct omap_overlay_manager *mgr,
461 enum omap_dss_color_key_type type,
464 dispc_set_trans_key(mgr->id, type, trans_key);
466 static void omap_dss_mgr_get_trans_key_type_and_value(
467 struct omap_overlay_manager *mgr,
468 enum omap_dss_color_key_type *type,
471 dispc_get_trans_key(mgr->id, type, trans_key);
474 static void omap_dss_mgr_enable_trans_key(struct omap_overlay_manager *mgr,
477 dispc_enable_trans_key(mgr->id, enable);
479 static void omap_dss_mgr_enable_alpha_blending(struct omap_overlay_manager *mgr,
482 dispc_enable_alpha_blending(mgr->id, enable);
484 static bool omap_dss_mgr_get_alpha_blending_status(
485 struct omap_overlay_manager *mgr)
487 return dispc_alpha_blending_enabled(mgr->id);
489 static u32 omap_dss_mgr_get_default_color(struct omap_overlay_manager *mgr)
491 return dispc_get_default_color(mgr->id);
493 static bool omap_dss_mgr_get_trans_key_status(struct omap_overlay_manager *mgr)
495 return dispc_trans_key_enabled(mgr->id);
498 static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
501 list_add_tail(&manager->list, &manager_list);
504 int dss_init_overlay_managers(struct platform_device *pdev)
508 INIT_LIST_HEAD(&manager_list);
512 for (i = 0; i < 2; ++i) {
513 struct omap_overlay_manager *mgr;
514 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
521 mgr->id = OMAP_DSS_CHANNEL_LCD;
522 mgr->supported_displays =
523 OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
524 OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
528 mgr->id = OMAP_DSS_CHANNEL_DIGIT;
529 mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
533 mgr->set_display = &omap_dss_set_display,
534 mgr->unset_display = &omap_dss_unset_display,
535 mgr->apply = &omap_dss_mgr_apply,
536 mgr->set_default_color = &omap_dss_mgr_set_def_color,
537 mgr->set_trans_key_type_and_value =
538 &omap_dss_mgr_set_trans_key_type_and_value,
539 mgr->get_trans_key_type_and_value =
540 &omap_dss_mgr_get_trans_key_type_and_value,
541 mgr->enable_trans_key = &omap_dss_mgr_enable_trans_key,
542 mgr->get_trans_key_status = &omap_dss_mgr_get_trans_key_status,
543 mgr->enable_alpha_blending =
544 &omap_dss_mgr_enable_alpha_blending;
545 mgr->get_alpha_blending_status =
546 omap_dss_mgr_get_alpha_blending_status;
547 mgr->get_default_color = &omap_dss_mgr_get_default_color;
548 mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC,
550 dss_overlay_setup_dispc_manager(mgr);
552 omap_dss_add_overlay_manager(mgr);
554 r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
555 &pdev->dev.kobj, "manager%d", i);
558 DSSERR("failed to create sysfs file\n");
566 void dss_uninit_overlay_managers(struct platform_device *pdev)
568 struct omap_overlay_manager *mgr;
570 while (!list_empty(&manager_list)) {
571 mgr = list_first_entry(&manager_list,
572 struct omap_overlay_manager, list);
573 list_del(&mgr->list);
574 kobject_del(&mgr->kobj);
575 kobject_put(&mgr->kobj);
582 int omap_dss_get_num_overlay_managers(void)
586 EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
588 struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
591 struct omap_overlay_manager *mgr;
593 list_for_each_entry(mgr, &manager_list, list) {
600 EXPORT_SYMBOL(omap_dss_get_overlay_manager);
603 static int ovl_mgr_apply_l4(struct omap_overlay_manager *mgr)
605 DSSDBG("omap_dss_mgr_apply_l4(%s)\n", mgr->name);