apply.c 21 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /*
  2. * Copyright (C) 2011 Texas Instruments
  3. * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 as published by
  7. * the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #define DSS_SUBSYS_NAME "APPLY"
  18. #include <linux/kernel.h>
  19. #include <linux/slab.h>
  20. #include <linux/spinlock.h>
  21. #include <linux/jiffies.h>
  22. #include <video/omapdss.h>
  23. #include "dss.h"
  24. #include "dss_features.h"
  25. /*
  26. * We have 4 levels of cache for the dispc settings. First two are in SW and
  27. * the latter two in HW.
  28. *
  29. * set_info()
  30. * v
  31. * +--------------------+
  32. * | user_info |
  33. * +--------------------+
  34. * v
  35. * apply()
  36. * v
  37. * +--------------------+
  38. * | info |
  39. * +--------------------+
  40. * v
  41. * write_regs()
  42. * v
  43. * +--------------------+
  44. * | shadow registers |
  45. * +--------------------+
  46. * v
  47. * VFP or lcd/digit_enable
  48. * v
  49. * +--------------------+
  50. * | registers |
  51. * +--------------------+
  52. */
  53. struct ovl_priv_data {
  54. bool user_info_dirty;
  55. struct omap_overlay_info user_info;
  56. bool info_dirty;
  57. struct omap_overlay_info info;
  58. bool shadow_info_dirty;
  59. bool extra_info_dirty;
  60. bool shadow_extra_info_dirty;
  61. bool enabled;
  62. enum omap_channel channel;
  63. u32 fifo_low, fifo_high;
  64. };
  65. struct mgr_priv_data {
  66. bool user_info_dirty;
  67. struct omap_overlay_manager_info user_info;
  68. bool info_dirty;
  69. struct omap_overlay_manager_info info;
  70. bool shadow_info_dirty;
  71. /* If true, GO bit is up and shadow registers cannot be written.
  72. * Never true for manual update displays */
  73. bool busy;
  74. /* If true, dispc output is enabled */
  75. bool updating;
  76. /* If true, a display is enabled using this manager */
  77. bool enabled;
  78. };
  79. static struct {
  80. struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
  81. struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
  82. bool irq_enabled;
  83. } dss_data;
  84. /* protects dss_data */
  85. static spinlock_t data_lock;
  86. /* lock for blocking functions */
  87. static DEFINE_MUTEX(apply_lock);
  88. static void dss_register_vsync_isr(void);
  89. static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
  90. {
  91. return &dss_data.ovl_priv_data_array[ovl->id];
  92. }
  93. static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
  94. {
  95. return &dss_data.mgr_priv_data_array[mgr->id];
  96. }
  97. void dss_apply_init(void)
  98. {
  99. const int num_ovls = dss_feat_get_num_ovls();
  100. int i;
  101. spin_lock_init(&data_lock);
  102. for (i = 0; i < num_ovls; ++i) {
  103. struct ovl_priv_data *op;
  104. op = &dss_data.ovl_priv_data_array[i];
  105. op->info.global_alpha = 255;
  106. switch (i) {
  107. case 0:
  108. op->info.zorder = 0;
  109. break;
  110. case 1:
  111. op->info.zorder =
  112. dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
  113. break;
  114. case 2:
  115. op->info.zorder =
  116. dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
  117. break;
  118. case 3:
  119. op->info.zorder =
  120. dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
  121. break;
  122. }
  123. op->user_info = op->info;
  124. }
  125. }
  126. static bool ovl_manual_update(struct omap_overlay *ovl)
  127. {
  128. return ovl->manager->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
  129. }
  130. static bool mgr_manual_update(struct omap_overlay_manager *mgr)
  131. {
  132. return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
  133. }
  134. static bool need_isr(void)
  135. {
  136. const int num_mgrs = dss_feat_get_num_mgrs();
  137. int i;
  138. for (i = 0; i < num_mgrs; ++i) {
  139. struct omap_overlay_manager *mgr;
  140. struct mgr_priv_data *mp;
  141. struct omap_overlay *ovl;
  142. mgr = omap_dss_get_overlay_manager(i);
  143. mp = get_mgr_priv(mgr);
  144. if (!mp->enabled)
  145. continue;
  146. if (mgr_manual_update(mgr)) {
  147. /* to catch FRAMEDONE */
  148. if (mp->updating)
  149. return true;
  150. } else {
  151. /* to catch GO bit going down */
  152. if (mp->busy)
  153. return true;
  154. /* to write new values to registers */
  155. if (mp->info_dirty)
  156. return true;
  157. list_for_each_entry(ovl, &mgr->overlays, list) {
  158. struct ovl_priv_data *op;
  159. op = get_ovl_priv(ovl);
  160. if (!op->enabled)
  161. continue;
  162. /* to write new values to registers */
  163. if (op->info_dirty || op->extra_info_dirty)
  164. return true;
  165. }
  166. }
  167. }
  168. return false;
  169. }
  170. static bool need_go(struct omap_overlay_manager *mgr)
  171. {
  172. struct omap_overlay *ovl;
  173. struct mgr_priv_data *mp;
  174. struct ovl_priv_data *op;
  175. mp = get_mgr_priv(mgr);
  176. if (mp->shadow_info_dirty)
  177. return true;
  178. list_for_each_entry(ovl, &mgr->overlays, list) {
  179. op = get_ovl_priv(ovl);
  180. if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
  181. return true;
  182. }
  183. return false;
  184. }
  185. int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
  186. {
  187. unsigned long timeout = msecs_to_jiffies(500);
  188. struct mgr_priv_data *mp;
  189. u32 irq;
  190. int r;
  191. int i;
  192. struct omap_dss_device *dssdev = mgr->device;
  193. if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
  194. return 0;
  195. if (mgr_manual_update(mgr))
  196. return 0;
  197. irq = dispc_mgr_get_vsync_irq(mgr->id);
  198. mp = get_mgr_priv(mgr);
  199. i = 0;
  200. while (1) {
  201. unsigned long flags;
  202. bool shadow_dirty, dirty;
  203. spin_lock_irqsave(&data_lock, flags);
  204. dirty = mp->info_dirty;
  205. shadow_dirty = mp->shadow_info_dirty;
  206. spin_unlock_irqrestore(&data_lock, flags);
  207. if (!dirty && !shadow_dirty) {
  208. r = 0;
  209. break;
  210. }
  211. /* 4 iterations is the worst case:
  212. * 1 - initial iteration, dirty = true (between VFP and VSYNC)
  213. * 2 - first VSYNC, dirty = true
  214. * 3 - dirty = false, shadow_dirty = true
  215. * 4 - shadow_dirty = false */
  216. if (i++ == 3) {
  217. DSSERR("mgr(%d)->wait_for_go() not finishing\n",
  218. mgr->id);
  219. r = 0;
  220. break;
  221. }
  222. r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
  223. if (r == -ERESTARTSYS)
  224. break;
  225. if (r) {
  226. DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
  227. break;
  228. }
  229. }
  230. return r;
  231. }
  232. int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
  233. {
  234. unsigned long timeout = msecs_to_jiffies(500);
  235. struct ovl_priv_data *op;
  236. struct omap_dss_device *dssdev;
  237. u32 irq;
  238. int r;
  239. int i;
  240. if (!ovl->manager)
  241. return 0;
  242. dssdev = ovl->manager->device;
  243. if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
  244. return 0;
  245. if (ovl_manual_update(ovl))
  246. return 0;
  247. irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
  248. op = get_ovl_priv(ovl);
  249. i = 0;
  250. while (1) {
  251. unsigned long flags;
  252. bool shadow_dirty, dirty;
  253. spin_lock_irqsave(&data_lock, flags);
  254. dirty = op->info_dirty;
  255. shadow_dirty = op->shadow_info_dirty;
  256. spin_unlock_irqrestore(&data_lock, flags);
  257. if (!dirty && !shadow_dirty) {
  258. r = 0;
  259. break;
  260. }
  261. /* 4 iterations is the worst case:
  262. * 1 - initial iteration, dirty = true (between VFP and VSYNC)
  263. * 2 - first VSYNC, dirty = true
  264. * 3 - dirty = false, shadow_dirty = true
  265. * 4 - shadow_dirty = false */
  266. if (i++ == 3) {
  267. DSSERR("ovl(%d)->wait_for_go() not finishing\n",
  268. ovl->id);
  269. r = 0;
  270. break;
  271. }
  272. r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
  273. if (r == -ERESTARTSYS)
  274. break;
  275. if (r) {
  276. DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
  277. break;
  278. }
  279. }
  280. return r;
  281. }
  282. static void dss_ovl_write_regs(struct omap_overlay *ovl)
  283. {
  284. struct ovl_priv_data *op = get_ovl_priv(ovl);
  285. struct omap_overlay_info *oi;
  286. bool ilace, replication;
  287. struct mgr_priv_data *mp;
  288. int r;
  289. DSSDBGF("%d", ovl->id);
  290. if (!op->enabled || !op->info_dirty)
  291. return;
  292. oi = &op->info;
  293. replication = dss_use_replication(ovl->manager->device, oi->color_mode);
  294. ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC;
  295. r = dispc_ovl_setup(ovl->id, oi, ilace, replication);
  296. if (r) {
  297. /*
  298. * We can't do much here, as this function can be called from
  299. * vsync interrupt.
  300. */
  301. DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
  302. /* This will leave fifo configurations in a nonoptimal state */
  303. op->enabled = false;
  304. dispc_ovl_enable(ovl->id, false);
  305. return;
  306. }
  307. mp = get_mgr_priv(ovl->manager);
  308. op->info_dirty = false;
  309. if (mp->updating)
  310. op->shadow_info_dirty = true;
  311. }
  312. static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
  313. {
  314. struct ovl_priv_data *op = get_ovl_priv(ovl);
  315. struct mgr_priv_data *mp;
  316. DSSDBGF("%d", ovl->id);
  317. if (!op->extra_info_dirty)
  318. return;
  319. /* note: write also when op->enabled == false, so that the ovl gets
  320. * disabled */
  321. dispc_ovl_enable(ovl->id, op->enabled);
  322. dispc_ovl_set_channel_out(ovl->id, op->channel);
  323. dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
  324. mp = get_mgr_priv(ovl->manager);
  325. op->extra_info_dirty = false;
  326. if (mp->updating)
  327. op->shadow_extra_info_dirty = true;
  328. }
  329. static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
  330. {
  331. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  332. struct omap_overlay *ovl;
  333. DSSDBGF("%d", mgr->id);
  334. if (!mp->enabled)
  335. return;
  336. WARN_ON(mp->busy);
  337. /* Commit overlay settings */
  338. list_for_each_entry(ovl, &mgr->overlays, list) {
  339. dss_ovl_write_regs(ovl);
  340. dss_ovl_write_regs_extra(ovl);
  341. }
  342. if (mp->info_dirty) {
  343. dispc_mgr_setup(mgr->id, &mp->info);
  344. mp->info_dirty = false;
  345. if (mp->updating)
  346. mp->shadow_info_dirty = true;
  347. }
  348. }
  349. static void dss_write_regs(void)
  350. {
  351. const int num_mgrs = omap_dss_get_num_overlay_managers();
  352. int i;
  353. for (i = 0; i < num_mgrs; ++i) {
  354. struct omap_overlay_manager *mgr;
  355. struct mgr_priv_data *mp;
  356. mgr = omap_dss_get_overlay_manager(i);
  357. mp = get_mgr_priv(mgr);
  358. if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
  359. continue;
  360. dss_mgr_write_regs(mgr);
  361. if (need_go(mgr)) {
  362. mp->busy = true;
  363. if (!dss_data.irq_enabled && need_isr())
  364. dss_register_vsync_isr();
  365. dispc_mgr_go(mgr->id);
  366. }
  367. }
  368. }
  369. void dss_mgr_start_update(struct omap_overlay_manager *mgr)
  370. {
  371. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  372. unsigned long flags;
  373. spin_lock_irqsave(&data_lock, flags);
  374. WARN_ON(mp->updating);
  375. dss_mgr_write_regs(mgr);
  376. mp->updating = true;
  377. if (!dss_data.irq_enabled && need_isr())
  378. dss_register_vsync_isr();
  379. dispc_mgr_enable(mgr->id, true);
  380. spin_unlock_irqrestore(&data_lock, flags);
  381. }
  382. static void dss_apply_irq_handler(void *data, u32 mask);
  383. static void dss_register_vsync_isr(void)
  384. {
  385. const int num_mgrs = dss_feat_get_num_mgrs();
  386. u32 mask;
  387. int r, i;
  388. mask = 0;
  389. for (i = 0; i < num_mgrs; ++i)
  390. mask |= dispc_mgr_get_vsync_irq(i);
  391. for (i = 0; i < num_mgrs; ++i)
  392. mask |= dispc_mgr_get_framedone_irq(i);
  393. r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
  394. WARN_ON(r);
  395. dss_data.irq_enabled = true;
  396. }
  397. static void dss_unregister_vsync_isr(void)
  398. {
  399. const int num_mgrs = dss_feat_get_num_mgrs();
  400. u32 mask;
  401. int r, i;
  402. mask = 0;
  403. for (i = 0; i < num_mgrs; ++i)
  404. mask |= dispc_mgr_get_vsync_irq(i);
  405. for (i = 0; i < num_mgrs; ++i)
  406. mask |= dispc_mgr_get_framedone_irq(i);
  407. r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
  408. WARN_ON(r);
  409. dss_data.irq_enabled = false;
  410. }
  411. static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
  412. {
  413. struct omap_overlay *ovl;
  414. struct mgr_priv_data *mp;
  415. struct ovl_priv_data *op;
  416. mp = get_mgr_priv(mgr);
  417. mp->shadow_info_dirty = false;
  418. list_for_each_entry(ovl, &mgr->overlays, list) {
  419. op = get_ovl_priv(ovl);
  420. op->shadow_info_dirty = false;
  421. op->shadow_extra_info_dirty = false;
  422. }
  423. }
  424. static void dss_apply_irq_handler(void *data, u32 mask)
  425. {
  426. const int num_mgrs = dss_feat_get_num_mgrs();
  427. int i;
  428. spin_lock(&data_lock);
  429. /* clear busy, updating flags, shadow_dirty flags */
  430. for (i = 0; i < num_mgrs; i++) {
  431. struct omap_overlay_manager *mgr;
  432. struct mgr_priv_data *mp;
  433. mgr = omap_dss_get_overlay_manager(i);
  434. mp = get_mgr_priv(mgr);
  435. if (!mp->enabled)
  436. continue;
  437. mp->updating = dispc_mgr_is_enabled(i);
  438. if (!mgr_manual_update(mgr)) {
  439. mp->busy = dispc_mgr_go_busy(i);
  440. if (!mp->busy)
  441. mgr_clear_shadow_dirty(mgr);
  442. } else {
  443. if (!mp->updating)
  444. mgr_clear_shadow_dirty(mgr);
  445. }
  446. }
  447. dss_write_regs();
  448. if (!need_isr())
  449. dss_unregister_vsync_isr();
  450. spin_unlock(&data_lock);
  451. }
  452. static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
  453. {
  454. struct ovl_priv_data *op;
  455. op = get_ovl_priv(ovl);
  456. if (!op->user_info_dirty)
  457. return;
  458. op->user_info_dirty = false;
  459. op->info_dirty = true;
  460. op->info = op->user_info;
  461. }
  462. static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
  463. {
  464. struct mgr_priv_data *mp;
  465. mp = get_mgr_priv(mgr);
  466. if (!mp->user_info_dirty)
  467. return;
  468. mp->user_info_dirty = false;
  469. mp->info_dirty = true;
  470. mp->info = mp->user_info;
  471. }
  472. int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
  473. {
  474. int r;
  475. unsigned long flags;
  476. struct omap_overlay *ovl;
  477. DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
  478. r = dispc_runtime_get();
  479. if (r)
  480. return r;
  481. spin_lock_irqsave(&data_lock, flags);
  482. /* Configure overlays */
  483. list_for_each_entry(ovl, &mgr->overlays, list)
  484. omap_dss_mgr_apply_ovl(ovl);
  485. /* Configure manager */
  486. omap_dss_mgr_apply_mgr(mgr);
  487. dss_write_regs();
  488. spin_unlock_irqrestore(&data_lock, flags);
  489. dispc_runtime_put();
  490. return r;
  491. }
  492. static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
  493. {
  494. struct ovl_priv_data *op;
  495. op = get_ovl_priv(ovl);
  496. if (op->enabled == enable)
  497. return;
  498. op->enabled = enable;
  499. op->extra_info_dirty = true;
  500. }
  501. static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
  502. {
  503. struct ovl_priv_data *op = get_ovl_priv(ovl);
  504. struct omap_dss_device *dssdev;
  505. u32 size, burst_size;
  506. u32 fifo_low, fifo_high;
  507. dssdev = ovl->manager->device;
  508. size = dispc_ovl_get_fifo_size(ovl->id);
  509. burst_size = dispc_ovl_get_burst_size(ovl->id);
  510. switch (dssdev->type) {
  511. case OMAP_DISPLAY_TYPE_DPI:
  512. case OMAP_DISPLAY_TYPE_DBI:
  513. case OMAP_DISPLAY_TYPE_SDI:
  514. case OMAP_DISPLAY_TYPE_VENC:
  515. case OMAP_DISPLAY_TYPE_HDMI:
  516. default_get_overlay_fifo_thresholds(ovl->id, size,
  517. burst_size, &fifo_low, &fifo_high);
  518. break;
  519. #ifdef CONFIG_OMAP2_DSS_DSI
  520. case OMAP_DISPLAY_TYPE_DSI:
  521. dsi_get_overlay_fifo_thresholds(ovl->id, size,
  522. burst_size, &fifo_low, &fifo_high);
  523. break;
  524. #endif
  525. default:
  526. BUG();
  527. }
  528. op->fifo_low = fifo_low;
  529. op->fifo_high = fifo_high;
  530. op->extra_info_dirty = true;
  531. }
  532. static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
  533. {
  534. struct omap_overlay *ovl;
  535. struct ovl_priv_data *op;
  536. struct mgr_priv_data *mp;
  537. mp = get_mgr_priv(mgr);
  538. if (!mp->enabled)
  539. return;
  540. list_for_each_entry(ovl, &mgr->overlays, list) {
  541. op = get_ovl_priv(ovl);
  542. if (!op->enabled)
  543. continue;
  544. dss_ovl_setup_fifo(ovl);
  545. }
  546. }
  547. void dss_mgr_enable(struct omap_overlay_manager *mgr)
  548. {
  549. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  550. unsigned long flags;
  551. mutex_lock(&apply_lock);
  552. spin_lock_irqsave(&data_lock, flags);
  553. mp->enabled = true;
  554. dss_mgr_setup_fifos(mgr);
  555. dss_write_regs();
  556. if (!mgr_manual_update(mgr))
  557. mp->updating = true;
  558. spin_unlock_irqrestore(&data_lock, flags);
  559. if (!mgr_manual_update(mgr))
  560. dispc_mgr_enable(mgr->id, true);
  561. mutex_unlock(&apply_lock);
  562. }
  563. void dss_mgr_disable(struct omap_overlay_manager *mgr)
  564. {
  565. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  566. unsigned long flags;
  567. mutex_lock(&apply_lock);
  568. if (!mgr_manual_update(mgr))
  569. dispc_mgr_enable(mgr->id, false);
  570. spin_lock_irqsave(&data_lock, flags);
  571. mp->updating = false;
  572. mp->enabled = false;
  573. spin_unlock_irqrestore(&data_lock, flags);
  574. mutex_unlock(&apply_lock);
  575. }
  576. int dss_mgr_set_info(struct omap_overlay_manager *mgr,
  577. struct omap_overlay_manager_info *info)
  578. {
  579. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  580. unsigned long flags;
  581. spin_lock_irqsave(&data_lock, flags);
  582. mp->user_info = *info;
  583. mp->user_info_dirty = true;
  584. spin_unlock_irqrestore(&data_lock, flags);
  585. return 0;
  586. }
  587. void dss_mgr_get_info(struct omap_overlay_manager *mgr,
  588. struct omap_overlay_manager_info *info)
  589. {
  590. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  591. unsigned long flags;
  592. spin_lock_irqsave(&data_lock, flags);
  593. *info = mp->user_info;
  594. spin_unlock_irqrestore(&data_lock, flags);
  595. }
  596. int dss_mgr_set_device(struct omap_overlay_manager *mgr,
  597. struct omap_dss_device *dssdev)
  598. {
  599. int r;
  600. mutex_lock(&apply_lock);
  601. if (dssdev->manager) {
  602. DSSERR("display '%s' already has a manager '%s'\n",
  603. dssdev->name, dssdev->manager->name);
  604. r = -EINVAL;
  605. goto err;
  606. }
  607. if ((mgr->supported_displays & dssdev->type) == 0) {
  608. DSSERR("display '%s' does not support manager '%s'\n",
  609. dssdev->name, mgr->name);
  610. r = -EINVAL;
  611. goto err;
  612. }
  613. dssdev->manager = mgr;
  614. mgr->device = dssdev;
  615. mutex_unlock(&apply_lock);
  616. return 0;
  617. err:
  618. mutex_unlock(&apply_lock);
  619. return r;
  620. }
  621. int dss_mgr_unset_device(struct omap_overlay_manager *mgr)
  622. {
  623. int r;
  624. mutex_lock(&apply_lock);
  625. if (!mgr->device) {
  626. DSSERR("failed to unset display, display not set.\n");
  627. r = -EINVAL;
  628. goto err;
  629. }
  630. /*
  631. * Don't allow currently enabled displays to have the overlay manager
  632. * pulled out from underneath them
  633. */
  634. if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) {
  635. r = -EINVAL;
  636. goto err;
  637. }
  638. mgr->device->manager = NULL;
  639. mgr->device = NULL;
  640. mutex_unlock(&apply_lock);
  641. return 0;
  642. err:
  643. mutex_unlock(&apply_lock);
  644. return r;
  645. }
  646. int dss_ovl_set_info(struct omap_overlay *ovl,
  647. struct omap_overlay_info *info)
  648. {
  649. struct ovl_priv_data *op = get_ovl_priv(ovl);
  650. unsigned long flags;
  651. spin_lock_irqsave(&data_lock, flags);
  652. op->user_info = *info;
  653. op->user_info_dirty = true;
  654. spin_unlock_irqrestore(&data_lock, flags);
  655. return 0;
  656. }
  657. void dss_ovl_get_info(struct omap_overlay *ovl,
  658. struct omap_overlay_info *info)
  659. {
  660. struct ovl_priv_data *op = get_ovl_priv(ovl);
  661. unsigned long flags;
  662. spin_lock_irqsave(&data_lock, flags);
  663. *info = op->user_info;
  664. spin_unlock_irqrestore(&data_lock, flags);
  665. }
  666. int dss_ovl_set_manager(struct omap_overlay *ovl,
  667. struct omap_overlay_manager *mgr)
  668. {
  669. struct ovl_priv_data *op = get_ovl_priv(ovl);
  670. unsigned long flags;
  671. int r;
  672. if (!mgr)
  673. return -EINVAL;
  674. mutex_lock(&apply_lock);
  675. if (ovl->manager) {
  676. DSSERR("overlay '%s' already has a manager '%s'\n",
  677. ovl->name, ovl->manager->name);
  678. r = -EINVAL;
  679. goto err;
  680. }
  681. spin_lock_irqsave(&data_lock, flags);
  682. if (op->enabled) {
  683. spin_unlock_irqrestore(&data_lock, flags);
  684. DSSERR("overlay has to be disabled to change the manager\n");
  685. r = -EINVAL;
  686. goto err;
  687. }
  688. op->channel = mgr->id;
  689. op->extra_info_dirty = true;
  690. ovl->manager = mgr;
  691. list_add_tail(&ovl->list, &mgr->overlays);
  692. spin_unlock_irqrestore(&data_lock, flags);
  693. /* XXX: When there is an overlay on a DSI manual update display, and
  694. * the overlay is first disabled, then moved to tv, and enabled, we
  695. * seem to get SYNC_LOST_DIGIT error.
  696. *
  697. * Waiting doesn't seem to help, but updating the manual update display
  698. * after disabling the overlay seems to fix this. This hints that the
  699. * overlay is perhaps somehow tied to the LCD output until the output
  700. * is updated.
  701. *
  702. * Userspace workaround for this is to update the LCD after disabling
  703. * the overlay, but before moving the overlay to TV.
  704. */
  705. mutex_unlock(&apply_lock);
  706. return 0;
  707. err:
  708. mutex_unlock(&apply_lock);
  709. return r;
  710. }
  711. int dss_ovl_unset_manager(struct omap_overlay *ovl)
  712. {
  713. struct ovl_priv_data *op = get_ovl_priv(ovl);
  714. unsigned long flags;
  715. int r;
  716. mutex_lock(&apply_lock);
  717. if (!ovl->manager) {
  718. DSSERR("failed to detach overlay: manager not set\n");
  719. r = -EINVAL;
  720. goto err;
  721. }
  722. spin_lock_irqsave(&data_lock, flags);
  723. if (op->enabled) {
  724. spin_unlock_irqrestore(&data_lock, flags);
  725. DSSERR("overlay has to be disabled to unset the manager\n");
  726. r = -EINVAL;
  727. goto err;
  728. }
  729. op->channel = -1;
  730. ovl->manager = NULL;
  731. list_del(&ovl->list);
  732. spin_unlock_irqrestore(&data_lock, flags);
  733. mutex_unlock(&apply_lock);
  734. return 0;
  735. err:
  736. mutex_unlock(&apply_lock);
  737. return r;
  738. }
  739. bool dss_ovl_is_enabled(struct omap_overlay *ovl)
  740. {
  741. struct ovl_priv_data *op = get_ovl_priv(ovl);
  742. unsigned long flags;
  743. bool e;
  744. spin_lock_irqsave(&data_lock, flags);
  745. e = op->enabled;
  746. spin_unlock_irqrestore(&data_lock, flags);
  747. return e;
  748. }
  749. int dss_ovl_enable(struct omap_overlay *ovl)
  750. {
  751. struct ovl_priv_data *op = get_ovl_priv(ovl);
  752. unsigned long flags;
  753. int r;
  754. mutex_lock(&apply_lock);
  755. if (ovl->manager == NULL || ovl->manager->device == NULL) {
  756. r = -EINVAL;
  757. goto err;
  758. }
  759. spin_lock_irqsave(&data_lock, flags);
  760. dss_apply_ovl_enable(ovl, true);
  761. dss_ovl_setup_fifo(ovl);
  762. dss_write_regs();
  763. spin_unlock_irqrestore(&data_lock, flags);
  764. mutex_unlock(&apply_lock);
  765. return 0;
  766. err:
  767. mutex_unlock(&apply_lock);
  768. return r;
  769. }
  770. int dss_ovl_disable(struct omap_overlay *ovl)
  771. {
  772. struct ovl_priv_data *op = get_ovl_priv(ovl);
  773. unsigned long flags;
  774. int r;
  775. mutex_lock(&apply_lock);
  776. if (ovl->manager == NULL || ovl->manager->device == NULL) {
  777. r = -EINVAL;
  778. goto err;
  779. }
  780. spin_lock_irqsave(&data_lock, flags);
  781. dss_apply_ovl_enable(ovl, false);
  782. dss_write_regs();
  783. spin_unlock_irqrestore(&data_lock, flags);
  784. mutex_unlock(&apply_lock);
  785. return 0;
  786. err:
  787. mutex_unlock(&apply_lock);
  788. return r;
  789. }