| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 1 | /* | 
|  | 2 | * linux/drivers/video/omap2/dss/overlay.c | 
|  | 3 | * | 
|  | 4 | * Copyright (C) 2009 Nokia Corporation | 
|  | 5 | * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> | 
|  | 6 | * | 
|  | 7 | * Some code and ideas taken from drivers/video/omap/ driver | 
|  | 8 | * by Imre Deak. | 
|  | 9 | * | 
|  | 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. | 
|  | 13 | * | 
|  | 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 | 
|  | 17 | * more details. | 
|  | 18 | * | 
|  | 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/>. | 
|  | 21 | */ | 
|  | 22 |  | 
|  | 23 | #define DSS_SUBSYS_NAME "OVERLAY" | 
|  | 24 |  | 
|  | 25 | #include <linux/kernel.h> | 
|  | 26 | #include <linux/module.h> | 
|  | 27 | #include <linux/err.h> | 
|  | 28 | #include <linux/sysfs.h> | 
|  | 29 | #include <linux/kobject.h> | 
|  | 30 | #include <linux/platform_device.h> | 
|  | 31 | #include <linux/delay.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 32 | #include <linux/slab.h> | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 33 |  | 
| Tomi Valkeinen | a0b38cc | 2011-05-11 14:05:07 +0300 | [diff] [blame] | 34 | #include <video/omapdss.h> | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 35 | #include <plat/cpu.h> | 
|  | 36 |  | 
|  | 37 | #include "dss.h" | 
| Archit Taneja | a0acb55 | 2010-09-15 19:20:00 +0530 | [diff] [blame] | 38 | #include "dss_features.h" | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 39 |  | 
|  | 40 | static int num_overlays; | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 41 | static struct omap_overlay *overlays; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 42 |  | 
|  | 43 | static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) | 
|  | 44 | { | 
|  | 45 | return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name); | 
|  | 46 | } | 
|  | 47 |  | 
|  | 48 | static ssize_t overlay_manager_show(struct omap_overlay *ovl, char *buf) | 
|  | 49 | { | 
|  | 50 | return snprintf(buf, PAGE_SIZE, "%s\n", | 
|  | 51 | ovl->manager ? ovl->manager->name : "<none>"); | 
|  | 52 | } | 
|  | 53 |  | 
|  | 54 | static ssize_t overlay_manager_store(struct omap_overlay *ovl, const char *buf, | 
|  | 55 | size_t size) | 
|  | 56 | { | 
|  | 57 | int i, r; | 
|  | 58 | struct omap_overlay_manager *mgr = NULL; | 
|  | 59 | struct omap_overlay_manager *old_mgr; | 
|  | 60 | int len = size; | 
|  | 61 |  | 
|  | 62 | if (buf[size-1] == '\n') | 
|  | 63 | --len; | 
|  | 64 |  | 
|  | 65 | if (len > 0) { | 
|  | 66 | for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { | 
|  | 67 | mgr = omap_dss_get_overlay_manager(i); | 
|  | 68 |  | 
| Archit Taneja | f3c77d6 | 2010-08-02 15:14:11 +0200 | [diff] [blame] | 69 | if (sysfs_streq(buf, mgr->name)) | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 70 | break; | 
|  | 71 |  | 
|  | 72 | mgr = NULL; | 
|  | 73 | } | 
|  | 74 | } | 
|  | 75 |  | 
|  | 76 | if (len > 0 && mgr == NULL) | 
|  | 77 | return -EINVAL; | 
|  | 78 |  | 
|  | 79 | if (mgr) | 
|  | 80 | DSSDBG("manager %s found\n", mgr->name); | 
|  | 81 |  | 
|  | 82 | if (mgr == ovl->manager) | 
|  | 83 | return size; | 
|  | 84 |  | 
|  | 85 | old_mgr = ovl->manager; | 
|  | 86 |  | 
| Tomi Valkeinen | 4fbafaf | 2011-05-27 10:52:19 +0300 | [diff] [blame] | 87 | r = dispc_runtime_get(); | 
|  | 88 | if (r) | 
|  | 89 | return r; | 
|  | 90 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 91 | /* detach old manager */ | 
|  | 92 | if (old_mgr) { | 
|  | 93 | r = ovl->unset_manager(ovl); | 
|  | 94 | if (r) { | 
|  | 95 | DSSERR("detach failed\n"); | 
| Tomi Valkeinen | 4fbafaf | 2011-05-27 10:52:19 +0300 | [diff] [blame] | 96 | goto err; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 97 | } | 
|  | 98 |  | 
|  | 99 | r = old_mgr->apply(old_mgr); | 
|  | 100 | if (r) | 
| Tomi Valkeinen | 4fbafaf | 2011-05-27 10:52:19 +0300 | [diff] [blame] | 101 | goto err; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 102 | } | 
|  | 103 |  | 
|  | 104 | if (mgr) { | 
|  | 105 | r = ovl->set_manager(ovl, mgr); | 
|  | 106 | if (r) { | 
|  | 107 | DSSERR("Failed to attach overlay\n"); | 
| Tomi Valkeinen | 4fbafaf | 2011-05-27 10:52:19 +0300 | [diff] [blame] | 108 | goto err; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 109 | } | 
|  | 110 |  | 
|  | 111 | r = mgr->apply(mgr); | 
|  | 112 | if (r) | 
| Tomi Valkeinen | 4fbafaf | 2011-05-27 10:52:19 +0300 | [diff] [blame] | 113 | goto err; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 114 | } | 
|  | 115 |  | 
| Tomi Valkeinen | 4fbafaf | 2011-05-27 10:52:19 +0300 | [diff] [blame] | 116 | dispc_runtime_put(); | 
|  | 117 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 118 | return size; | 
| Tomi Valkeinen | 4fbafaf | 2011-05-27 10:52:19 +0300 | [diff] [blame] | 119 |  | 
|  | 120 | err: | 
|  | 121 | dispc_runtime_put(); | 
|  | 122 | return r; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 123 | } | 
|  | 124 |  | 
|  | 125 | static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) | 
|  | 126 | { | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 127 | struct omap_overlay_info info; | 
|  | 128 |  | 
|  | 129 | ovl->get_overlay_info(ovl, &info); | 
|  | 130 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 131 | return snprintf(buf, PAGE_SIZE, "%d,%d\n", | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 132 | info.width, info.height); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 133 | } | 
|  | 134 |  | 
|  | 135 | static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf) | 
|  | 136 | { | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 137 | struct omap_overlay_info info; | 
|  | 138 |  | 
|  | 139 | ovl->get_overlay_info(ovl, &info); | 
|  | 140 |  | 
|  | 141 | return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 142 | } | 
|  | 143 |  | 
|  | 144 | static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf) | 
|  | 145 | { | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 146 | struct omap_overlay_info info; | 
|  | 147 |  | 
|  | 148 | ovl->get_overlay_info(ovl, &info); | 
|  | 149 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 150 | return snprintf(buf, PAGE_SIZE, "%d,%d\n", | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 151 | info.pos_x, info.pos_y); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 152 | } | 
|  | 153 |  | 
|  | 154 | static ssize_t overlay_position_store(struct omap_overlay *ovl, | 
|  | 155 | const char *buf, size_t size) | 
|  | 156 | { | 
|  | 157 | int r; | 
|  | 158 | char *last; | 
|  | 159 | struct omap_overlay_info info; | 
|  | 160 |  | 
|  | 161 | ovl->get_overlay_info(ovl, &info); | 
|  | 162 |  | 
|  | 163 | info.pos_x = simple_strtoul(buf, &last, 10); | 
|  | 164 | ++last; | 
|  | 165 | if (last - buf >= size) | 
|  | 166 | return -EINVAL; | 
|  | 167 |  | 
|  | 168 | info.pos_y = simple_strtoul(last, &last, 10); | 
|  | 169 |  | 
|  | 170 | r = ovl->set_overlay_info(ovl, &info); | 
|  | 171 | if (r) | 
|  | 172 | return r; | 
|  | 173 |  | 
|  | 174 | if (ovl->manager) { | 
|  | 175 | r = ovl->manager->apply(ovl->manager); | 
|  | 176 | if (r) | 
|  | 177 | return r; | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | return size; | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf) | 
|  | 184 | { | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 185 | struct omap_overlay_info info; | 
|  | 186 |  | 
|  | 187 | ovl->get_overlay_info(ovl, &info); | 
|  | 188 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 189 | return snprintf(buf, PAGE_SIZE, "%d,%d\n", | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 190 | info.out_width, info.out_height); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 191 | } | 
|  | 192 |  | 
|  | 193 | static ssize_t overlay_output_size_store(struct omap_overlay *ovl, | 
|  | 194 | const char *buf, size_t size) | 
|  | 195 | { | 
|  | 196 | int r; | 
|  | 197 | char *last; | 
|  | 198 | struct omap_overlay_info info; | 
|  | 199 |  | 
|  | 200 | ovl->get_overlay_info(ovl, &info); | 
|  | 201 |  | 
|  | 202 | info.out_width = simple_strtoul(buf, &last, 10); | 
|  | 203 | ++last; | 
|  | 204 | if (last - buf >= size) | 
|  | 205 | return -EINVAL; | 
|  | 206 |  | 
|  | 207 | info.out_height = simple_strtoul(last, &last, 10); | 
|  | 208 |  | 
|  | 209 | r = ovl->set_overlay_info(ovl, &info); | 
|  | 210 | if (r) | 
|  | 211 | return r; | 
|  | 212 |  | 
|  | 213 | if (ovl->manager) { | 
|  | 214 | r = ovl->manager->apply(ovl->manager); | 
|  | 215 | if (r) | 
|  | 216 | return r; | 
|  | 217 | } | 
|  | 218 |  | 
|  | 219 | return size; | 
|  | 220 | } | 
|  | 221 |  | 
|  | 222 | static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) | 
|  | 223 | { | 
| Tomi Valkeinen | aaa874a | 2011-11-15 16:37:53 +0200 | [diff] [blame] | 224 | return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl)); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 225 | } | 
|  | 226 |  | 
|  | 227 | static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, | 
|  | 228 | size_t size) | 
|  | 229 | { | 
| Tomi Valkeinen | e3a26ae | 2011-08-15 15:55:55 +0300 | [diff] [blame] | 230 | int r; | 
|  | 231 | bool enable; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 232 |  | 
| Tomi Valkeinen | e3a26ae | 2011-08-15 15:55:55 +0300 | [diff] [blame] | 233 | r = strtobool(buf, &enable); | 
| Tomi Valkeinen | e3502ce | 2011-04-04 15:40:23 +0300 | [diff] [blame] | 234 | if (r) | 
|  | 235 | return r; | 
|  | 236 |  | 
| Tomi Valkeinen | aaa874a | 2011-11-15 16:37:53 +0200 | [diff] [blame] | 237 | if (enable) | 
|  | 238 | r = ovl->enable(ovl); | 
|  | 239 | else | 
|  | 240 | r = ovl->disable(ovl); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 241 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 242 | if (r) | 
|  | 243 | return r; | 
|  | 244 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 245 | return size; | 
|  | 246 | } | 
|  | 247 |  | 
|  | 248 | static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf) | 
|  | 249 | { | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 250 | struct omap_overlay_info info; | 
|  | 251 |  | 
|  | 252 | ovl->get_overlay_info(ovl, &info); | 
|  | 253 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 254 | return snprintf(buf, PAGE_SIZE, "%d\n", | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 255 | info.global_alpha); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 256 | } | 
|  | 257 |  | 
|  | 258 | static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, | 
|  | 259 | const char *buf, size_t size) | 
|  | 260 | { | 
|  | 261 | int r; | 
| Tomi Valkeinen | e3502ce | 2011-04-04 15:40:23 +0300 | [diff] [blame] | 262 | u8 alpha; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 263 | struct omap_overlay_info info; | 
|  | 264 |  | 
| Tomi Valkeinen | f6dc815 | 2011-08-15 15:18:20 +0300 | [diff] [blame] | 265 | if ((ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) == 0) | 
| Tomi Valkeinen | 332e9d7 | 2011-05-27 14:22:16 +0300 | [diff] [blame] | 266 | return -ENODEV; | 
|  | 267 |  | 
| Tomi Valkeinen | e3502ce | 2011-04-04 15:40:23 +0300 | [diff] [blame] | 268 | r = kstrtou8(buf, 0, &alpha); | 
|  | 269 | if (r) | 
|  | 270 | return r; | 
|  | 271 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 272 | ovl->get_overlay_info(ovl, &info); | 
|  | 273 |  | 
| Tomi Valkeinen | f6dc815 | 2011-08-15 15:18:20 +0300 | [diff] [blame] | 274 | info.global_alpha = alpha; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 275 |  | 
|  | 276 | r = ovl->set_overlay_info(ovl, &info); | 
|  | 277 | if (r) | 
|  | 278 | return r; | 
|  | 279 |  | 
|  | 280 | if (ovl->manager) { | 
|  | 281 | r = ovl->manager->apply(ovl->manager); | 
|  | 282 | if (r) | 
|  | 283 | return r; | 
|  | 284 | } | 
|  | 285 |  | 
|  | 286 | return size; | 
|  | 287 | } | 
|  | 288 |  | 
| Rajkumar N | fd28a39 | 2010-11-04 12:28:42 +0100 | [diff] [blame] | 289 | static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl, | 
|  | 290 | char *buf) | 
|  | 291 | { | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 292 | struct omap_overlay_info info; | 
|  | 293 |  | 
|  | 294 | ovl->get_overlay_info(ovl, &info); | 
|  | 295 |  | 
| Rajkumar N | fd28a39 | 2010-11-04 12:28:42 +0100 | [diff] [blame] | 296 | return snprintf(buf, PAGE_SIZE, "%d\n", | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 297 | info.pre_mult_alpha); | 
| Rajkumar N | fd28a39 | 2010-11-04 12:28:42 +0100 | [diff] [blame] | 298 | } | 
|  | 299 |  | 
|  | 300 | static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, | 
|  | 301 | const char *buf, size_t size) | 
|  | 302 | { | 
|  | 303 | int r; | 
| Tomi Valkeinen | e3502ce | 2011-04-04 15:40:23 +0300 | [diff] [blame] | 304 | u8 alpha; | 
| Rajkumar N | fd28a39 | 2010-11-04 12:28:42 +0100 | [diff] [blame] | 305 | struct omap_overlay_info info; | 
|  | 306 |  | 
| Tomi Valkeinen | f6dc815 | 2011-08-15 15:18:20 +0300 | [diff] [blame] | 307 | if ((ovl->caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) | 
|  | 308 | return -ENODEV; | 
|  | 309 |  | 
| Tomi Valkeinen | e3502ce | 2011-04-04 15:40:23 +0300 | [diff] [blame] | 310 | r = kstrtou8(buf, 0, &alpha); | 
|  | 311 | if (r) | 
|  | 312 | return r; | 
|  | 313 |  | 
| Rajkumar N | fd28a39 | 2010-11-04 12:28:42 +0100 | [diff] [blame] | 314 | ovl->get_overlay_info(ovl, &info); | 
|  | 315 |  | 
| Tomi Valkeinen | f6dc815 | 2011-08-15 15:18:20 +0300 | [diff] [blame] | 316 | info.pre_mult_alpha = alpha; | 
| Rajkumar N | fd28a39 | 2010-11-04 12:28:42 +0100 | [diff] [blame] | 317 |  | 
|  | 318 | r = ovl->set_overlay_info(ovl, &info); | 
|  | 319 | if (r) | 
|  | 320 | return r; | 
|  | 321 |  | 
|  | 322 | if (ovl->manager) { | 
|  | 323 | r = ovl->manager->apply(ovl->manager); | 
|  | 324 | if (r) | 
|  | 325 | return r; | 
|  | 326 | } | 
|  | 327 |  | 
|  | 328 | return size; | 
|  | 329 | } | 
|  | 330 |  | 
| Archit Taneja | 5412870 | 2011-09-08 11:29:17 +0530 | [diff] [blame] | 331 | static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf) | 
|  | 332 | { | 
| Tomi Valkeinen | c1a9feb | 2011-11-16 14:11:56 +0200 | [diff] [blame] | 333 | struct omap_overlay_info info; | 
|  | 334 |  | 
|  | 335 | ovl->get_overlay_info(ovl, &info); | 
|  | 336 |  | 
|  | 337 | return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder); | 
| Archit Taneja | 5412870 | 2011-09-08 11:29:17 +0530 | [diff] [blame] | 338 | } | 
|  | 339 |  | 
|  | 340 | static ssize_t overlay_zorder_store(struct omap_overlay *ovl, | 
|  | 341 | const char *buf, size_t size) | 
|  | 342 | { | 
|  | 343 | int r; | 
|  | 344 | u8 zorder; | 
|  | 345 | struct omap_overlay_info info; | 
|  | 346 |  | 
|  | 347 | if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) | 
|  | 348 | return -ENODEV; | 
|  | 349 |  | 
|  | 350 | r = kstrtou8(buf, 0, &zorder); | 
|  | 351 | if (r) | 
|  | 352 | return r; | 
|  | 353 |  | 
|  | 354 | ovl->get_overlay_info(ovl, &info); | 
|  | 355 |  | 
|  | 356 | info.zorder = zorder; | 
|  | 357 |  | 
|  | 358 | r = ovl->set_overlay_info(ovl, &info); | 
|  | 359 | if (r) | 
|  | 360 | return r; | 
|  | 361 |  | 
|  | 362 | if (ovl->manager) { | 
|  | 363 | r = ovl->manager->apply(ovl->manager); | 
|  | 364 | if (r) | 
|  | 365 | return r; | 
|  | 366 | } | 
|  | 367 |  | 
|  | 368 | return size; | 
|  | 369 | } | 
|  | 370 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 371 | struct overlay_attribute { | 
|  | 372 | struct attribute attr; | 
|  | 373 | ssize_t (*show)(struct omap_overlay *, char *); | 
|  | 374 | ssize_t	(*store)(struct omap_overlay *, const char *, size_t); | 
|  | 375 | }; | 
|  | 376 |  | 
|  | 377 | #define OVERLAY_ATTR(_name, _mode, _show, _store) \ | 
|  | 378 | struct overlay_attribute overlay_attr_##_name = \ | 
|  | 379 | __ATTR(_name, _mode, _show, _store) | 
|  | 380 |  | 
|  | 381 | static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL); | 
|  | 382 | static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR, | 
|  | 383 | overlay_manager_show, overlay_manager_store); | 
|  | 384 | static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL); | 
|  | 385 | static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL); | 
|  | 386 | static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR, | 
|  | 387 | overlay_position_show, overlay_position_store); | 
|  | 388 | static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR, | 
|  | 389 | overlay_output_size_show, overlay_output_size_store); | 
|  | 390 | static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR, | 
|  | 391 | overlay_enabled_show, overlay_enabled_store); | 
|  | 392 | static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR, | 
|  | 393 | overlay_global_alpha_show, overlay_global_alpha_store); | 
| Rajkumar N | fd28a39 | 2010-11-04 12:28:42 +0100 | [diff] [blame] | 394 | static OVERLAY_ATTR(pre_mult_alpha, S_IRUGO|S_IWUSR, | 
|  | 395 | overlay_pre_mult_alpha_show, | 
|  | 396 | overlay_pre_mult_alpha_store); | 
| Archit Taneja | 5412870 | 2011-09-08 11:29:17 +0530 | [diff] [blame] | 397 | static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR, | 
|  | 398 | overlay_zorder_show, overlay_zorder_store); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 399 |  | 
|  | 400 | static struct attribute *overlay_sysfs_attrs[] = { | 
|  | 401 | &overlay_attr_name.attr, | 
|  | 402 | &overlay_attr_manager.attr, | 
|  | 403 | &overlay_attr_input_size.attr, | 
|  | 404 | &overlay_attr_screen_width.attr, | 
|  | 405 | &overlay_attr_position.attr, | 
|  | 406 | &overlay_attr_output_size.attr, | 
|  | 407 | &overlay_attr_enabled.attr, | 
|  | 408 | &overlay_attr_global_alpha.attr, | 
| Rajkumar N | fd28a39 | 2010-11-04 12:28:42 +0100 | [diff] [blame] | 409 | &overlay_attr_pre_mult_alpha.attr, | 
| Archit Taneja | 5412870 | 2011-09-08 11:29:17 +0530 | [diff] [blame] | 410 | &overlay_attr_zorder.attr, | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 411 | NULL | 
|  | 412 | }; | 
|  | 413 |  | 
|  | 414 | static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr, | 
|  | 415 | char *buf) | 
|  | 416 | { | 
|  | 417 | struct omap_overlay *overlay; | 
|  | 418 | struct overlay_attribute *overlay_attr; | 
|  | 419 |  | 
|  | 420 | overlay = container_of(kobj, struct omap_overlay, kobj); | 
|  | 421 | overlay_attr = container_of(attr, struct overlay_attribute, attr); | 
|  | 422 |  | 
|  | 423 | if (!overlay_attr->show) | 
|  | 424 | return -ENOENT; | 
|  | 425 |  | 
|  | 426 | return overlay_attr->show(overlay, buf); | 
|  | 427 | } | 
|  | 428 |  | 
|  | 429 | static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr, | 
|  | 430 | const char *buf, size_t size) | 
|  | 431 | { | 
|  | 432 | struct omap_overlay *overlay; | 
|  | 433 | struct overlay_attribute *overlay_attr; | 
|  | 434 |  | 
|  | 435 | overlay = container_of(kobj, struct omap_overlay, kobj); | 
|  | 436 | overlay_attr = container_of(attr, struct overlay_attribute, attr); | 
|  | 437 |  | 
|  | 438 | if (!overlay_attr->store) | 
|  | 439 | return -ENOENT; | 
|  | 440 |  | 
|  | 441 | return overlay_attr->store(overlay, buf, size); | 
|  | 442 | } | 
|  | 443 |  | 
| Emese Revfy | 52cf25d | 2010-01-19 02:58:23 +0100 | [diff] [blame] | 444 | static const struct sysfs_ops overlay_sysfs_ops = { | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 445 | .show = overlay_attr_show, | 
|  | 446 | .store = overlay_attr_store, | 
|  | 447 | }; | 
|  | 448 |  | 
|  | 449 | static struct kobj_type overlay_ktype = { | 
|  | 450 | .sysfs_ops = &overlay_sysfs_ops, | 
|  | 451 | .default_attrs = overlay_sysfs_attrs, | 
|  | 452 | }; | 
|  | 453 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 454 | int omap_dss_get_num_overlays(void) | 
|  | 455 | { | 
|  | 456 | return num_overlays; | 
|  | 457 | } | 
|  | 458 | EXPORT_SYMBOL(omap_dss_get_num_overlays); | 
|  | 459 |  | 
|  | 460 | struct omap_overlay *omap_dss_get_overlay(int num) | 
|  | 461 | { | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 462 | if (num >= num_overlays) | 
|  | 463 | return NULL; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 464 |  | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 465 | return &overlays[num]; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 466 | } | 
|  | 467 | EXPORT_SYMBOL(omap_dss_get_overlay); | 
|  | 468 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 469 | void dss_init_overlays(struct platform_device *pdev) | 
|  | 470 | { | 
|  | 471 | int i, r; | 
|  | 472 |  | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 473 | num_overlays = dss_feat_get_num_ovls(); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 474 |  | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 475 | overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays, | 
|  | 476 | GFP_KERNEL); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 477 |  | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 478 | BUG_ON(overlays == NULL); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 479 |  | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 480 | for (i = 0; i < num_overlays; ++i) { | 
|  | 481 | struct omap_overlay *ovl = &overlays[i]; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 482 |  | 
|  | 483 | switch (i) { | 
|  | 484 | case 0: | 
|  | 485 | ovl->name = "gfx"; | 
|  | 486 | ovl->id = OMAP_DSS_GFX; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 487 | break; | 
|  | 488 | case 1: | 
|  | 489 | ovl->name = "vid1"; | 
|  | 490 | ovl->id = OMAP_DSS_VIDEO1; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 491 | break; | 
|  | 492 | case 2: | 
|  | 493 | ovl->name = "vid2"; | 
|  | 494 | ovl->id = OMAP_DSS_VIDEO2; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 495 | break; | 
| Archit Taneja | b8c095b | 2011-09-13 18:20:33 +0530 | [diff] [blame] | 496 | case 3: | 
|  | 497 | ovl->name = "vid3"; | 
|  | 498 | ovl->id = OMAP_DSS_VIDEO3; | 
| Archit Taneja | b8c095b | 2011-09-13 18:20:33 +0530 | [diff] [blame] | 499 | break; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 500 | } | 
|  | 501 |  | 
| Tomi Valkeinen | aaa874a | 2011-11-15 16:37:53 +0200 | [diff] [blame] | 502 | ovl->is_enabled = &dss_ovl_is_enabled; | 
|  | 503 | ovl->enable = &dss_ovl_enable; | 
|  | 504 | ovl->disable = &dss_ovl_disable; | 
| Tomi Valkeinen | f77b307 | 2011-11-15 12:11:11 +0200 | [diff] [blame] | 505 | ovl->set_manager = &dss_ovl_set_manager; | 
|  | 506 | ovl->unset_manager = &dss_ovl_unset_manager; | 
|  | 507 | ovl->set_overlay_info = &dss_ovl_set_info; | 
|  | 508 | ovl->get_overlay_info = &dss_ovl_get_info; | 
| Tomi Valkeinen | 550a8f6 | 2011-11-04 13:00:10 +0200 | [diff] [blame] | 509 | ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 510 |  | 
| Tomi Valkeinen | 67019db | 2011-08-15 15:18:15 +0300 | [diff] [blame] | 511 | ovl->caps = dss_feat_get_overlay_caps(ovl->id); | 
| Archit Taneja | a0acb55 | 2010-09-15 19:20:00 +0530 | [diff] [blame] | 512 | ovl->supported_modes = | 
|  | 513 | dss_feat_get_supported_color_modes(ovl->id); | 
|  | 514 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 515 | r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, | 
|  | 516 | &pdev->dev.kobj, "overlay%d", i); | 
|  | 517 |  | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 518 | if (r) | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 519 | DSSERR("failed to create sysfs file\n"); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 520 | } | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 521 | } | 
|  | 522 |  | 
|  | 523 | /* connect overlays to the new device, if not already connected. if force | 
|  | 524 | * selected, connect always. */ | 
|  | 525 | void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) | 
|  | 526 | { | 
|  | 527 | int i; | 
|  | 528 | struct omap_overlay_manager *lcd_mgr; | 
|  | 529 | struct omap_overlay_manager *tv_mgr; | 
| Sumit Semwal | 18faa1b | 2010-12-02 11:27:14 +0000 | [diff] [blame] | 530 | struct omap_overlay_manager *lcd2_mgr = NULL; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 531 | struct omap_overlay_manager *mgr = NULL; | 
|  | 532 |  | 
|  | 533 | lcd_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD); | 
|  | 534 | tv_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_TV); | 
| Sumit Semwal | 18faa1b | 2010-12-02 11:27:14 +0000 | [diff] [blame] | 535 | if (dss_has_feature(FEAT_MGR_LCD2)) | 
|  | 536 | lcd2_mgr = omap_dss_get_overlay_manager(OMAP_DSS_OVL_MGR_LCD2); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 537 |  | 
| Sumit Semwal | 18faa1b | 2010-12-02 11:27:14 +0000 | [diff] [blame] | 538 | if (dssdev->channel == OMAP_DSS_CHANNEL_LCD2) { | 
|  | 539 | if (!lcd2_mgr->device || force) { | 
|  | 540 | if (lcd2_mgr->device) | 
|  | 541 | lcd2_mgr->unset_device(lcd2_mgr); | 
|  | 542 | lcd2_mgr->set_device(lcd2_mgr, dssdev); | 
|  | 543 | mgr = lcd2_mgr; | 
|  | 544 | } | 
| Mythri P K | b119601 | 2011-03-08 17:15:54 +0530 | [diff] [blame] | 545 | } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC | 
|  | 546 | && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) { | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 547 | if (!lcd_mgr->device || force) { | 
|  | 548 | if (lcd_mgr->device) | 
|  | 549 | lcd_mgr->unset_device(lcd_mgr); | 
|  | 550 | lcd_mgr->set_device(lcd_mgr, dssdev); | 
|  | 551 | mgr = lcd_mgr; | 
|  | 552 | } | 
|  | 553 | } | 
|  | 554 |  | 
| Mythri P K | b119601 | 2011-03-08 17:15:54 +0530 | [diff] [blame] | 555 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC | 
|  | 556 | || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 557 | if (!tv_mgr->device || force) { | 
|  | 558 | if (tv_mgr->device) | 
|  | 559 | tv_mgr->unset_device(tv_mgr); | 
|  | 560 | tv_mgr->set_device(tv_mgr, dssdev); | 
|  | 561 | mgr = tv_mgr; | 
|  | 562 | } | 
|  | 563 | } | 
|  | 564 |  | 
|  | 565 | if (mgr) { | 
| Tomi Valkeinen | 4fbafaf | 2011-05-27 10:52:19 +0300 | [diff] [blame] | 566 | dispc_runtime_get(); | 
|  | 567 |  | 
| Archit Taneja | a0acb55 | 2010-09-15 19:20:00 +0530 | [diff] [blame] | 568 | for (i = 0; i < dss_feat_get_num_ovls(); i++) { | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 569 | struct omap_overlay *ovl; | 
|  | 570 | ovl = omap_dss_get_overlay(i); | 
|  | 571 | if (!ovl->manager || force) { | 
|  | 572 | if (ovl->manager) | 
| Tomi Valkeinen | f77b307 | 2011-11-15 12:11:11 +0200 | [diff] [blame] | 573 | ovl->unset_manager(ovl); | 
|  | 574 | ovl->set_manager(ovl, mgr); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 575 | } | 
|  | 576 | } | 
| Tomi Valkeinen | 4fbafaf | 2011-05-27 10:52:19 +0300 | [diff] [blame] | 577 |  | 
|  | 578 | dispc_runtime_put(); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 579 | } | 
|  | 580 | } | 
|  | 581 |  | 
|  | 582 | void dss_uninit_overlays(struct platform_device *pdev) | 
|  | 583 | { | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 584 | int i; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 585 |  | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 586 | for (i = 0; i < num_overlays; ++i) { | 
|  | 587 | struct omap_overlay *ovl = &overlays[i]; | 
|  | 588 |  | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 589 | kobject_del(&ovl->kobj); | 
|  | 590 | kobject_put(&ovl->kobj); | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 591 | } | 
|  | 592 |  | 
| Tomi Valkeinen | 5845234 | 2011-11-05 10:39:59 +0200 | [diff] [blame] | 593 | kfree(overlays); | 
|  | 594 | overlays = NULL; | 
| Tomi Valkeinen | eed07e0 | 2009-08-07 13:43:20 +0300 | [diff] [blame] | 595 | num_overlays = 0; | 
|  | 596 | } | 
|  | 597 |  | 
| Tomi Valkeinen | 54540d4 | 2011-12-13 13:18:52 +0200 | [diff] [blame] | 598 | int dss_ovl_simple_check(struct omap_overlay *ovl, | 
|  | 599 | const struct omap_overlay_info *info) | 
|  | 600 | { | 
|  | 601 | if (info->paddr == 0) { | 
|  | 602 | DSSERR("check_overlay: paddr cannot be 0\n"); | 
|  | 603 | return -EINVAL; | 
|  | 604 | } | 
|  | 605 |  | 
|  | 606 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { | 
|  | 607 | if (info->out_width != 0 && info->width != info->out_width) { | 
|  | 608 | DSSERR("check_overlay: overlay %d doesn't support " | 
|  | 609 | "scaling\n", ovl->id); | 
|  | 610 | return -EINVAL; | 
|  | 611 | } | 
|  | 612 |  | 
|  | 613 | if (info->out_height != 0 && info->height != info->out_height) { | 
|  | 614 | DSSERR("check_overlay: overlay %d doesn't support " | 
|  | 615 | "scaling\n", ovl->id); | 
|  | 616 | return -EINVAL; | 
|  | 617 | } | 
|  | 618 | } | 
|  | 619 |  | 
|  | 620 | if ((ovl->supported_modes & info->color_mode) == 0) { | 
|  | 621 | DSSERR("check_overlay: overlay %d doesn't support mode %d\n", | 
|  | 622 | ovl->id, info->color_mode); | 
|  | 623 | return -EINVAL; | 
|  | 624 | } | 
|  | 625 |  | 
|  | 626 | if (info->zorder >= omap_dss_get_num_overlays()) { | 
|  | 627 | DSSERR("check_overlay: zorder %d too high\n", info->zorder); | 
|  | 628 | return -EINVAL; | 
|  | 629 | } | 
|  | 630 |  | 
|  | 631 | return 0; | 
|  | 632 | } | 
|  | 633 |  | 
| Tomi Valkeinen | 6ac48d1 | 2011-12-08 10:32:37 +0200 | [diff] [blame] | 634 | int dss_ovl_check(struct omap_overlay *ovl, | 
|  | 635 | struct omap_overlay_info *info, struct omap_dss_device *dssdev) | 
|  | 636 | { | 
|  | 637 | u16 outw, outh; | 
|  | 638 | u16 dw, dh; | 
|  | 639 |  | 
|  | 640 | if (dssdev == NULL) | 
|  | 641 | return 0; | 
|  | 642 |  | 
|  | 643 | dssdev->driver->get_resolution(dssdev, &dw, &dh); | 
|  | 644 |  | 
|  | 645 | if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { | 
|  | 646 | outw = info->width; | 
|  | 647 | outh = info->height; | 
|  | 648 | } else { | 
|  | 649 | if (info->out_width == 0) | 
|  | 650 | outw = info->width; | 
|  | 651 | else | 
|  | 652 | outw = info->out_width; | 
|  | 653 |  | 
|  | 654 | if (info->out_height == 0) | 
|  | 655 | outh = info->height; | 
|  | 656 | else | 
|  | 657 | outh = info->out_height; | 
|  | 658 | } | 
|  | 659 |  | 
|  | 660 | if (dw < info->pos_x + outw) { | 
|  | 661 | DSSERR("overlay %d horizontally not inside the display area " | 
|  | 662 | "(%d + %d >= %d)\n", | 
|  | 663 | ovl->id, info->pos_x, outw, dw); | 
|  | 664 | return -EINVAL; | 
|  | 665 | } | 
|  | 666 |  | 
|  | 667 | if (dh < info->pos_y + outh) { | 
|  | 668 | DSSERR("overlay %d vertically not inside the display area " | 
|  | 669 | "(%d + %d >= %d)\n", | 
|  | 670 | ovl->id, info->pos_y, outh, dh); | 
|  | 671 | return -EINVAL; | 
|  | 672 | } | 
|  | 673 |  | 
|  | 674 | return 0; | 
|  | 675 | } |