apply.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671
  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/module.h>
  20. #include <linux/slab.h>
  21. #include <linux/spinlock.h>
  22. #include <linux/jiffies.h>
  23. #include <video/omapdss.h>
  24. #include "dss.h"
  25. #include "dss_features.h"
  26. #include "dispc-compat.h"
  27. /*
  28. * We have 4 levels of cache for the dispc settings. First two are in SW and
  29. * the latter two in HW.
  30. *
  31. * set_info()
  32. * v
  33. * +--------------------+
  34. * | user_info |
  35. * +--------------------+
  36. * v
  37. * apply()
  38. * v
  39. * +--------------------+
  40. * | info |
  41. * +--------------------+
  42. * v
  43. * write_regs()
  44. * v
  45. * +--------------------+
  46. * | shadow registers |
  47. * +--------------------+
  48. * v
  49. * VFP or lcd/digit_enable
  50. * v
  51. * +--------------------+
  52. * | registers |
  53. * +--------------------+
  54. */
  55. struct ovl_priv_data {
  56. bool user_info_dirty;
  57. struct omap_overlay_info user_info;
  58. bool info_dirty;
  59. struct omap_overlay_info info;
  60. bool shadow_info_dirty;
  61. bool extra_info_dirty;
  62. bool shadow_extra_info_dirty;
  63. bool enabled;
  64. u32 fifo_low, fifo_high;
  65. /*
  66. * True if overlay is to be enabled. Used to check and calculate configs
  67. * for the overlay before it is enabled in the HW.
  68. */
  69. bool enabling;
  70. };
  71. struct mgr_priv_data {
  72. bool user_info_dirty;
  73. struct omap_overlay_manager_info user_info;
  74. bool info_dirty;
  75. struct omap_overlay_manager_info info;
  76. bool shadow_info_dirty;
  77. /* If true, GO bit is up and shadow registers cannot be written.
  78. * Never true for manual update displays */
  79. bool busy;
  80. /* If true, dispc output is enabled */
  81. bool updating;
  82. /* If true, a display is enabled using this manager */
  83. bool enabled;
  84. bool extra_info_dirty;
  85. bool shadow_extra_info_dirty;
  86. struct omap_video_timings timings;
  87. struct dss_lcd_mgr_config lcd_config;
  88. void (*framedone_handler)(void *);
  89. void *framedone_handler_data;
  90. };
  91. static struct {
  92. struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
  93. struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
  94. bool irq_enabled;
  95. } dss_data;
  96. /* protects dss_data */
  97. static spinlock_t data_lock;
  98. /* lock for blocking functions */
  99. static DEFINE_MUTEX(apply_lock);
  100. static DECLARE_COMPLETION(extra_updated_completion);
  101. static void dss_register_vsync_isr(void);
  102. static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
  103. {
  104. return &dss_data.ovl_priv_data_array[ovl->id];
  105. }
  106. static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
  107. {
  108. return &dss_data.mgr_priv_data_array[mgr->id];
  109. }
  110. static void apply_init_priv(void)
  111. {
  112. const int num_ovls = dss_feat_get_num_ovls();
  113. struct mgr_priv_data *mp;
  114. int i;
  115. spin_lock_init(&data_lock);
  116. for (i = 0; i < num_ovls; ++i) {
  117. struct ovl_priv_data *op;
  118. op = &dss_data.ovl_priv_data_array[i];
  119. op->info.global_alpha = 255;
  120. switch (i) {
  121. case 0:
  122. op->info.zorder = 0;
  123. break;
  124. case 1:
  125. op->info.zorder =
  126. dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
  127. break;
  128. case 2:
  129. op->info.zorder =
  130. dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
  131. break;
  132. case 3:
  133. op->info.zorder =
  134. dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
  135. break;
  136. }
  137. op->user_info = op->info;
  138. }
  139. /*
  140. * Initialize some of the lcd_config fields for TV manager, this lets
  141. * us prevent checking if the manager is LCD or TV at some places
  142. */
  143. mp = &dss_data.mgr_priv_data_array[OMAP_DSS_CHANNEL_DIGIT];
  144. mp->lcd_config.video_port_width = 24;
  145. mp->lcd_config.clock_info.lck_div = 1;
  146. mp->lcd_config.clock_info.pck_div = 1;
  147. }
  148. /*
  149. * A LCD manager's stallmode decides whether it is in manual or auto update. TV
  150. * manager is always auto update, stallmode field for TV manager is false by
  151. * default
  152. */
  153. static bool ovl_manual_update(struct omap_overlay *ovl)
  154. {
  155. struct mgr_priv_data *mp = get_mgr_priv(ovl->manager);
  156. return mp->lcd_config.stallmode;
  157. }
  158. static bool mgr_manual_update(struct omap_overlay_manager *mgr)
  159. {
  160. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  161. return mp->lcd_config.stallmode;
  162. }
  163. static int dss_check_settings_low(struct omap_overlay_manager *mgr,
  164. bool applying)
  165. {
  166. struct omap_overlay_info *oi;
  167. struct omap_overlay_manager_info *mi;
  168. struct omap_overlay *ovl;
  169. struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
  170. struct ovl_priv_data *op;
  171. struct mgr_priv_data *mp;
  172. mp = get_mgr_priv(mgr);
  173. if (!mp->enabled)
  174. return 0;
  175. if (applying && mp->user_info_dirty)
  176. mi = &mp->user_info;
  177. else
  178. mi = &mp->info;
  179. /* collect the infos to be tested into the array */
  180. list_for_each_entry(ovl, &mgr->overlays, list) {
  181. op = get_ovl_priv(ovl);
  182. if (!op->enabled && !op->enabling)
  183. oi = NULL;
  184. else if (applying && op->user_info_dirty)
  185. oi = &op->user_info;
  186. else
  187. oi = &op->info;
  188. ois[ovl->id] = oi;
  189. }
  190. return dss_mgr_check(mgr, mi, &mp->timings, &mp->lcd_config, ois);
  191. }
  192. /*
  193. * check manager and overlay settings using overlay_info from data->info
  194. */
  195. static int dss_check_settings(struct omap_overlay_manager *mgr)
  196. {
  197. return dss_check_settings_low(mgr, false);
  198. }
  199. /*
  200. * check manager and overlay settings using overlay_info from ovl->info if
  201. * dirty and from data->info otherwise
  202. */
  203. static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
  204. {
  205. return dss_check_settings_low(mgr, true);
  206. }
  207. static bool need_isr(void)
  208. {
  209. const int num_mgrs = dss_feat_get_num_mgrs();
  210. int i;
  211. for (i = 0; i < num_mgrs; ++i) {
  212. struct omap_overlay_manager *mgr;
  213. struct mgr_priv_data *mp;
  214. struct omap_overlay *ovl;
  215. mgr = omap_dss_get_overlay_manager(i);
  216. mp = get_mgr_priv(mgr);
  217. if (!mp->enabled)
  218. continue;
  219. if (mgr_manual_update(mgr)) {
  220. /* to catch FRAMEDONE */
  221. if (mp->updating)
  222. return true;
  223. } else {
  224. /* to catch GO bit going down */
  225. if (mp->busy)
  226. return true;
  227. /* to write new values to registers */
  228. if (mp->info_dirty)
  229. return true;
  230. /* to set GO bit */
  231. if (mp->shadow_info_dirty)
  232. return true;
  233. /*
  234. * NOTE: we don't check extra_info flags for disabled
  235. * managers, once the manager is enabled, the extra_info
  236. * related manager changes will be taken in by HW.
  237. */
  238. /* to write new values to registers */
  239. if (mp->extra_info_dirty)
  240. return true;
  241. /* to set GO bit */
  242. if (mp->shadow_extra_info_dirty)
  243. return true;
  244. list_for_each_entry(ovl, &mgr->overlays, list) {
  245. struct ovl_priv_data *op;
  246. op = get_ovl_priv(ovl);
  247. /*
  248. * NOTE: we check extra_info flags even for
  249. * disabled overlays, as extra_infos need to be
  250. * always written.
  251. */
  252. /* to write new values to registers */
  253. if (op->extra_info_dirty)
  254. return true;
  255. /* to set GO bit */
  256. if (op->shadow_extra_info_dirty)
  257. return true;
  258. if (!op->enabled)
  259. continue;
  260. /* to write new values to registers */
  261. if (op->info_dirty)
  262. return true;
  263. /* to set GO bit */
  264. if (op->shadow_info_dirty)
  265. return true;
  266. }
  267. }
  268. }
  269. return false;
  270. }
  271. static bool need_go(struct omap_overlay_manager *mgr)
  272. {
  273. struct omap_overlay *ovl;
  274. struct mgr_priv_data *mp;
  275. struct ovl_priv_data *op;
  276. mp = get_mgr_priv(mgr);
  277. if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty)
  278. return true;
  279. list_for_each_entry(ovl, &mgr->overlays, list) {
  280. op = get_ovl_priv(ovl);
  281. if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
  282. return true;
  283. }
  284. return false;
  285. }
  286. /* returns true if an extra_info field is currently being updated */
  287. static bool extra_info_update_ongoing(void)
  288. {
  289. const int num_mgrs = dss_feat_get_num_mgrs();
  290. int i;
  291. for (i = 0; i < num_mgrs; ++i) {
  292. struct omap_overlay_manager *mgr;
  293. struct omap_overlay *ovl;
  294. struct mgr_priv_data *mp;
  295. mgr = omap_dss_get_overlay_manager(i);
  296. mp = get_mgr_priv(mgr);
  297. if (!mp->enabled)
  298. continue;
  299. if (!mp->updating)
  300. continue;
  301. if (mp->extra_info_dirty || mp->shadow_extra_info_dirty)
  302. return true;
  303. list_for_each_entry(ovl, &mgr->overlays, list) {
  304. struct ovl_priv_data *op = get_ovl_priv(ovl);
  305. if (op->extra_info_dirty || op->shadow_extra_info_dirty)
  306. return true;
  307. }
  308. }
  309. return false;
  310. }
  311. /* wait until no extra_info updates are pending */
  312. static void wait_pending_extra_info_updates(void)
  313. {
  314. bool updating;
  315. unsigned long flags;
  316. unsigned long t;
  317. int r;
  318. spin_lock_irqsave(&data_lock, flags);
  319. updating = extra_info_update_ongoing();
  320. if (!updating) {
  321. spin_unlock_irqrestore(&data_lock, flags);
  322. return;
  323. }
  324. init_completion(&extra_updated_completion);
  325. spin_unlock_irqrestore(&data_lock, flags);
  326. t = msecs_to_jiffies(500);
  327. r = wait_for_completion_timeout(&extra_updated_completion, t);
  328. if (r == 0)
  329. DSSWARN("timeout in wait_pending_extra_info_updates\n");
  330. }
  331. static inline struct omap_dss_device *dss_ovl_get_device(struct omap_overlay *ovl)
  332. {
  333. return ovl->manager ?
  334. (ovl->manager->output ? ovl->manager->output->device : NULL) :
  335. NULL;
  336. }
  337. static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_manager *mgr)
  338. {
  339. return mgr->output ? mgr->output->device : NULL;
  340. }
  341. static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
  342. {
  343. unsigned long timeout = msecs_to_jiffies(500);
  344. struct omap_dss_device *dssdev = mgr->get_device(mgr);
  345. u32 irq;
  346. int r;
  347. r = dispc_runtime_get();
  348. if (r)
  349. return r;
  350. if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
  351. irq = DISPC_IRQ_EVSYNC_ODD;
  352. else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI)
  353. irq = DISPC_IRQ_EVSYNC_EVEN;
  354. else
  355. irq = dispc_mgr_get_vsync_irq(mgr->id);
  356. r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
  357. dispc_runtime_put();
  358. return r;
  359. }
  360. static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
  361. {
  362. unsigned long timeout = msecs_to_jiffies(500);
  363. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  364. u32 irq;
  365. unsigned long flags;
  366. int r;
  367. int i;
  368. spin_lock_irqsave(&data_lock, flags);
  369. if (mgr_manual_update(mgr)) {
  370. spin_unlock_irqrestore(&data_lock, flags);
  371. return 0;
  372. }
  373. if (!mp->enabled) {
  374. spin_unlock_irqrestore(&data_lock, flags);
  375. return 0;
  376. }
  377. spin_unlock_irqrestore(&data_lock, flags);
  378. r = dispc_runtime_get();
  379. if (r)
  380. return r;
  381. irq = dispc_mgr_get_vsync_irq(mgr->id);
  382. i = 0;
  383. while (1) {
  384. bool shadow_dirty, dirty;
  385. spin_lock_irqsave(&data_lock, flags);
  386. dirty = mp->info_dirty;
  387. shadow_dirty = mp->shadow_info_dirty;
  388. spin_unlock_irqrestore(&data_lock, flags);
  389. if (!dirty && !shadow_dirty) {
  390. r = 0;
  391. break;
  392. }
  393. /* 4 iterations is the worst case:
  394. * 1 - initial iteration, dirty = true (between VFP and VSYNC)
  395. * 2 - first VSYNC, dirty = true
  396. * 3 - dirty = false, shadow_dirty = true
  397. * 4 - shadow_dirty = false */
  398. if (i++ == 3) {
  399. DSSERR("mgr(%d)->wait_for_go() not finishing\n",
  400. mgr->id);
  401. r = 0;
  402. break;
  403. }
  404. r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
  405. if (r == -ERESTARTSYS)
  406. break;
  407. if (r) {
  408. DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
  409. break;
  410. }
  411. }
  412. dispc_runtime_put();
  413. return r;
  414. }
  415. static int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
  416. {
  417. unsigned long timeout = msecs_to_jiffies(500);
  418. struct ovl_priv_data *op;
  419. struct mgr_priv_data *mp;
  420. u32 irq;
  421. unsigned long flags;
  422. int r;
  423. int i;
  424. if (!ovl->manager)
  425. return 0;
  426. mp = get_mgr_priv(ovl->manager);
  427. spin_lock_irqsave(&data_lock, flags);
  428. if (ovl_manual_update(ovl)) {
  429. spin_unlock_irqrestore(&data_lock, flags);
  430. return 0;
  431. }
  432. if (!mp->enabled) {
  433. spin_unlock_irqrestore(&data_lock, flags);
  434. return 0;
  435. }
  436. spin_unlock_irqrestore(&data_lock, flags);
  437. r = dispc_runtime_get();
  438. if (r)
  439. return r;
  440. irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
  441. op = get_ovl_priv(ovl);
  442. i = 0;
  443. while (1) {
  444. bool shadow_dirty, dirty;
  445. spin_lock_irqsave(&data_lock, flags);
  446. dirty = op->info_dirty;
  447. shadow_dirty = op->shadow_info_dirty;
  448. spin_unlock_irqrestore(&data_lock, flags);
  449. if (!dirty && !shadow_dirty) {
  450. r = 0;
  451. break;
  452. }
  453. /* 4 iterations is the worst case:
  454. * 1 - initial iteration, dirty = true (between VFP and VSYNC)
  455. * 2 - first VSYNC, dirty = true
  456. * 3 - dirty = false, shadow_dirty = true
  457. * 4 - shadow_dirty = false */
  458. if (i++ == 3) {
  459. DSSERR("ovl(%d)->wait_for_go() not finishing\n",
  460. ovl->id);
  461. r = 0;
  462. break;
  463. }
  464. r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
  465. if (r == -ERESTARTSYS)
  466. break;
  467. if (r) {
  468. DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
  469. break;
  470. }
  471. }
  472. dispc_runtime_put();
  473. return r;
  474. }
  475. static void dss_ovl_write_regs(struct omap_overlay *ovl)
  476. {
  477. struct ovl_priv_data *op = get_ovl_priv(ovl);
  478. struct omap_overlay_info *oi;
  479. bool replication;
  480. struct mgr_priv_data *mp;
  481. int r;
  482. DSSDBG("writing ovl %d regs", ovl->id);
  483. if (!op->enabled || !op->info_dirty)
  484. return;
  485. oi = &op->info;
  486. mp = get_mgr_priv(ovl->manager);
  487. replication = dss_ovl_use_replication(mp->lcd_config, oi->color_mode);
  488. r = dispc_ovl_setup(ovl->id, oi, replication, &mp->timings, false);
  489. if (r) {
  490. /*
  491. * We can't do much here, as this function can be called from
  492. * vsync interrupt.
  493. */
  494. DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
  495. /* This will leave fifo configurations in a nonoptimal state */
  496. op->enabled = false;
  497. dispc_ovl_enable(ovl->id, false);
  498. return;
  499. }
  500. op->info_dirty = false;
  501. if (mp->updating)
  502. op->shadow_info_dirty = true;
  503. }
  504. static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
  505. {
  506. struct ovl_priv_data *op = get_ovl_priv(ovl);
  507. struct mgr_priv_data *mp;
  508. DSSDBG("writing ovl %d regs extra", ovl->id);
  509. if (!op->extra_info_dirty)
  510. return;
  511. /* note: write also when op->enabled == false, so that the ovl gets
  512. * disabled */
  513. dispc_ovl_enable(ovl->id, op->enabled);
  514. dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
  515. mp = get_mgr_priv(ovl->manager);
  516. op->extra_info_dirty = false;
  517. if (mp->updating)
  518. op->shadow_extra_info_dirty = true;
  519. }
  520. static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
  521. {
  522. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  523. struct omap_overlay *ovl;
  524. DSSDBG("writing mgr %d regs", mgr->id);
  525. if (!mp->enabled)
  526. return;
  527. WARN_ON(mp->busy);
  528. /* Commit overlay settings */
  529. list_for_each_entry(ovl, &mgr->overlays, list) {
  530. dss_ovl_write_regs(ovl);
  531. dss_ovl_write_regs_extra(ovl);
  532. }
  533. if (mp->info_dirty) {
  534. dispc_mgr_setup(mgr->id, &mp->info);
  535. mp->info_dirty = false;
  536. if (mp->updating)
  537. mp->shadow_info_dirty = true;
  538. }
  539. }
  540. static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
  541. {
  542. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  543. DSSDBG("writing mgr %d regs extra", mgr->id);
  544. if (!mp->extra_info_dirty)
  545. return;
  546. dispc_mgr_set_timings(mgr->id, &mp->timings);
  547. /* lcd_config parameters */
  548. if (dss_mgr_is_lcd(mgr->id))
  549. dispc_mgr_set_lcd_config(mgr->id, &mp->lcd_config);
  550. mp->extra_info_dirty = false;
  551. if (mp->updating)
  552. mp->shadow_extra_info_dirty = true;
  553. }
  554. static void dss_write_regs(void)
  555. {
  556. const int num_mgrs = omap_dss_get_num_overlay_managers();
  557. int i;
  558. for (i = 0; i < num_mgrs; ++i) {
  559. struct omap_overlay_manager *mgr;
  560. struct mgr_priv_data *mp;
  561. int r;
  562. mgr = omap_dss_get_overlay_manager(i);
  563. mp = get_mgr_priv(mgr);
  564. if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
  565. continue;
  566. r = dss_check_settings(mgr);
  567. if (r) {
  568. DSSERR("cannot write registers for manager %s: "
  569. "illegal configuration\n", mgr->name);
  570. continue;
  571. }
  572. dss_mgr_write_regs(mgr);
  573. dss_mgr_write_regs_extra(mgr);
  574. }
  575. }
  576. static void dss_set_go_bits(void)
  577. {
  578. const int num_mgrs = omap_dss_get_num_overlay_managers();
  579. int i;
  580. for (i = 0; i < num_mgrs; ++i) {
  581. struct omap_overlay_manager *mgr;
  582. struct mgr_priv_data *mp;
  583. mgr = omap_dss_get_overlay_manager(i);
  584. mp = get_mgr_priv(mgr);
  585. if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
  586. continue;
  587. if (!need_go(mgr))
  588. continue;
  589. mp->busy = true;
  590. if (!dss_data.irq_enabled && need_isr())
  591. dss_register_vsync_isr();
  592. dispc_mgr_go(mgr->id);
  593. }
  594. }
  595. static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
  596. {
  597. struct omap_overlay *ovl;
  598. struct mgr_priv_data *mp;
  599. struct ovl_priv_data *op;
  600. mp = get_mgr_priv(mgr);
  601. mp->shadow_info_dirty = false;
  602. mp->shadow_extra_info_dirty = false;
  603. list_for_each_entry(ovl, &mgr->overlays, list) {
  604. op = get_ovl_priv(ovl);
  605. op->shadow_info_dirty = false;
  606. op->shadow_extra_info_dirty = false;
  607. }
  608. }
  609. static void dss_mgr_start_update_compat(struct omap_overlay_manager *mgr)
  610. {
  611. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  612. unsigned long flags;
  613. int r;
  614. spin_lock_irqsave(&data_lock, flags);
  615. WARN_ON(mp->updating);
  616. r = dss_check_settings(mgr);
  617. if (r) {
  618. DSSERR("cannot start manual update: illegal configuration\n");
  619. spin_unlock_irqrestore(&data_lock, flags);
  620. return;
  621. }
  622. dss_mgr_write_regs(mgr);
  623. dss_mgr_write_regs_extra(mgr);
  624. mp->updating = true;
  625. if (!dss_data.irq_enabled && need_isr())
  626. dss_register_vsync_isr();
  627. dispc_mgr_enable_sync(mgr->id);
  628. spin_unlock_irqrestore(&data_lock, flags);
  629. }
  630. static void dss_apply_irq_handler(void *data, u32 mask);
  631. static void dss_register_vsync_isr(void)
  632. {
  633. const int num_mgrs = dss_feat_get_num_mgrs();
  634. u32 mask;
  635. int r, i;
  636. mask = 0;
  637. for (i = 0; i < num_mgrs; ++i)
  638. mask |= dispc_mgr_get_vsync_irq(i);
  639. for (i = 0; i < num_mgrs; ++i)
  640. mask |= dispc_mgr_get_framedone_irq(i);
  641. r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
  642. WARN_ON(r);
  643. dss_data.irq_enabled = true;
  644. }
  645. static void dss_unregister_vsync_isr(void)
  646. {
  647. const int num_mgrs = dss_feat_get_num_mgrs();
  648. u32 mask;
  649. int r, i;
  650. mask = 0;
  651. for (i = 0; i < num_mgrs; ++i)
  652. mask |= dispc_mgr_get_vsync_irq(i);
  653. for (i = 0; i < num_mgrs; ++i)
  654. mask |= dispc_mgr_get_framedone_irq(i);
  655. r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
  656. WARN_ON(r);
  657. dss_data.irq_enabled = false;
  658. }
  659. static void dss_apply_irq_handler(void *data, u32 mask)
  660. {
  661. const int num_mgrs = dss_feat_get_num_mgrs();
  662. int i;
  663. bool extra_updating;
  664. spin_lock(&data_lock);
  665. /* clear busy, updating flags, shadow_dirty flags */
  666. for (i = 0; i < num_mgrs; i++) {
  667. struct omap_overlay_manager *mgr;
  668. struct mgr_priv_data *mp;
  669. mgr = omap_dss_get_overlay_manager(i);
  670. mp = get_mgr_priv(mgr);
  671. if (!mp->enabled)
  672. continue;
  673. mp->updating = dispc_mgr_is_enabled(i);
  674. if (!mgr_manual_update(mgr)) {
  675. bool was_busy = mp->busy;
  676. mp->busy = dispc_mgr_go_busy(i);
  677. if (was_busy && !mp->busy)
  678. mgr_clear_shadow_dirty(mgr);
  679. }
  680. }
  681. dss_write_regs();
  682. dss_set_go_bits();
  683. extra_updating = extra_info_update_ongoing();
  684. if (!extra_updating)
  685. complete_all(&extra_updated_completion);
  686. /* call framedone handlers for manual update displays */
  687. for (i = 0; i < num_mgrs; i++) {
  688. struct omap_overlay_manager *mgr;
  689. struct mgr_priv_data *mp;
  690. mgr = omap_dss_get_overlay_manager(i);
  691. mp = get_mgr_priv(mgr);
  692. if (!mgr_manual_update(mgr) || !mp->framedone_handler)
  693. continue;
  694. if (mask & dispc_mgr_get_framedone_irq(i))
  695. mp->framedone_handler(mp->framedone_handler_data);
  696. }
  697. if (!need_isr())
  698. dss_unregister_vsync_isr();
  699. spin_unlock(&data_lock);
  700. }
  701. static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
  702. {
  703. struct ovl_priv_data *op;
  704. op = get_ovl_priv(ovl);
  705. if (!op->user_info_dirty)
  706. return;
  707. op->user_info_dirty = false;
  708. op->info_dirty = true;
  709. op->info = op->user_info;
  710. }
  711. static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
  712. {
  713. struct mgr_priv_data *mp;
  714. mp = get_mgr_priv(mgr);
  715. if (!mp->user_info_dirty)
  716. return;
  717. mp->user_info_dirty = false;
  718. mp->info_dirty = true;
  719. mp->info = mp->user_info;
  720. }
  721. static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
  722. {
  723. unsigned long flags;
  724. struct omap_overlay *ovl;
  725. int r;
  726. DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
  727. spin_lock_irqsave(&data_lock, flags);
  728. r = dss_check_settings_apply(mgr);
  729. if (r) {
  730. spin_unlock_irqrestore(&data_lock, flags);
  731. DSSERR("failed to apply settings: illegal configuration.\n");
  732. return r;
  733. }
  734. /* Configure overlays */
  735. list_for_each_entry(ovl, &mgr->overlays, list)
  736. omap_dss_mgr_apply_ovl(ovl);
  737. /* Configure manager */
  738. omap_dss_mgr_apply_mgr(mgr);
  739. dss_write_regs();
  740. dss_set_go_bits();
  741. spin_unlock_irqrestore(&data_lock, flags);
  742. return 0;
  743. }
  744. static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
  745. {
  746. struct ovl_priv_data *op;
  747. op = get_ovl_priv(ovl);
  748. if (op->enabled == enable)
  749. return;
  750. op->enabled = enable;
  751. op->extra_info_dirty = true;
  752. }
  753. static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
  754. u32 fifo_low, u32 fifo_high)
  755. {
  756. struct ovl_priv_data *op = get_ovl_priv(ovl);
  757. if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
  758. return;
  759. op->fifo_low = fifo_low;
  760. op->fifo_high = fifo_high;
  761. op->extra_info_dirty = true;
  762. }
  763. static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
  764. {
  765. struct ovl_priv_data *op = get_ovl_priv(ovl);
  766. u32 fifo_low, fifo_high;
  767. bool use_fifo_merge = false;
  768. if (!op->enabled && !op->enabling)
  769. return;
  770. dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
  771. use_fifo_merge, ovl_manual_update(ovl));
  772. dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
  773. }
  774. static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
  775. {
  776. struct omap_overlay *ovl;
  777. struct mgr_priv_data *mp;
  778. mp = get_mgr_priv(mgr);
  779. if (!mp->enabled)
  780. return;
  781. list_for_each_entry(ovl, &mgr->overlays, list)
  782. dss_ovl_setup_fifo(ovl);
  783. }
  784. static void dss_setup_fifos(void)
  785. {
  786. const int num_mgrs = omap_dss_get_num_overlay_managers();
  787. struct omap_overlay_manager *mgr;
  788. int i;
  789. for (i = 0; i < num_mgrs; ++i) {
  790. mgr = omap_dss_get_overlay_manager(i);
  791. dss_mgr_setup_fifos(mgr);
  792. }
  793. }
  794. static int dss_mgr_enable_compat(struct omap_overlay_manager *mgr)
  795. {
  796. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  797. unsigned long flags;
  798. int r;
  799. mutex_lock(&apply_lock);
  800. if (mp->enabled)
  801. goto out;
  802. spin_lock_irqsave(&data_lock, flags);
  803. mp->enabled = true;
  804. r = dss_check_settings(mgr);
  805. if (r) {
  806. DSSERR("failed to enable manager %d: check_settings failed\n",
  807. mgr->id);
  808. goto err;
  809. }
  810. dss_setup_fifos();
  811. dss_write_regs();
  812. dss_set_go_bits();
  813. if (!mgr_manual_update(mgr))
  814. mp->updating = true;
  815. if (!dss_data.irq_enabled && need_isr())
  816. dss_register_vsync_isr();
  817. spin_unlock_irqrestore(&data_lock, flags);
  818. if (!mgr_manual_update(mgr))
  819. dispc_mgr_enable_sync(mgr->id);
  820. out:
  821. mutex_unlock(&apply_lock);
  822. return 0;
  823. err:
  824. mp->enabled = false;
  825. spin_unlock_irqrestore(&data_lock, flags);
  826. mutex_unlock(&apply_lock);
  827. return r;
  828. }
  829. static void dss_mgr_disable_compat(struct omap_overlay_manager *mgr)
  830. {
  831. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  832. unsigned long flags;
  833. mutex_lock(&apply_lock);
  834. if (!mp->enabled)
  835. goto out;
  836. if (!mgr_manual_update(mgr))
  837. dispc_mgr_disable_sync(mgr->id);
  838. spin_lock_irqsave(&data_lock, flags);
  839. mp->updating = false;
  840. mp->enabled = false;
  841. spin_unlock_irqrestore(&data_lock, flags);
  842. out:
  843. mutex_unlock(&apply_lock);
  844. }
  845. static int dss_mgr_set_info(struct omap_overlay_manager *mgr,
  846. struct omap_overlay_manager_info *info)
  847. {
  848. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  849. unsigned long flags;
  850. int r;
  851. r = dss_mgr_simple_check(mgr, info);
  852. if (r)
  853. return r;
  854. spin_lock_irqsave(&data_lock, flags);
  855. mp->user_info = *info;
  856. mp->user_info_dirty = true;
  857. spin_unlock_irqrestore(&data_lock, flags);
  858. return 0;
  859. }
  860. static void dss_mgr_get_info(struct omap_overlay_manager *mgr,
  861. struct omap_overlay_manager_info *info)
  862. {
  863. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  864. unsigned long flags;
  865. spin_lock_irqsave(&data_lock, flags);
  866. *info = mp->user_info;
  867. spin_unlock_irqrestore(&data_lock, flags);
  868. }
  869. static int dss_mgr_set_output(struct omap_overlay_manager *mgr,
  870. struct omap_dss_output *output)
  871. {
  872. int r;
  873. mutex_lock(&apply_lock);
  874. if (mgr->output) {
  875. DSSERR("manager %s is already connected to an output\n",
  876. mgr->name);
  877. r = -EINVAL;
  878. goto err;
  879. }
  880. if ((mgr->supported_outputs & output->id) == 0) {
  881. DSSERR("output does not support manager %s\n",
  882. mgr->name);
  883. r = -EINVAL;
  884. goto err;
  885. }
  886. output->manager = mgr;
  887. mgr->output = output;
  888. mutex_unlock(&apply_lock);
  889. return 0;
  890. err:
  891. mutex_unlock(&apply_lock);
  892. return r;
  893. }
  894. static int dss_mgr_unset_output(struct omap_overlay_manager *mgr)
  895. {
  896. int r;
  897. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  898. unsigned long flags;
  899. mutex_lock(&apply_lock);
  900. if (!mgr->output) {
  901. DSSERR("failed to unset output, output not set\n");
  902. r = -EINVAL;
  903. goto err;
  904. }
  905. spin_lock_irqsave(&data_lock, flags);
  906. if (mp->enabled) {
  907. DSSERR("output can't be unset when manager is enabled\n");
  908. r = -EINVAL;
  909. goto err1;
  910. }
  911. spin_unlock_irqrestore(&data_lock, flags);
  912. mgr->output->manager = NULL;
  913. mgr->output = NULL;
  914. mutex_unlock(&apply_lock);
  915. return 0;
  916. err1:
  917. spin_unlock_irqrestore(&data_lock, flags);
  918. err:
  919. mutex_unlock(&apply_lock);
  920. return r;
  921. }
  922. static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
  923. const struct omap_video_timings *timings)
  924. {
  925. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  926. mp->timings = *timings;
  927. mp->extra_info_dirty = true;
  928. }
  929. static void dss_mgr_set_timings_compat(struct omap_overlay_manager *mgr,
  930. const struct omap_video_timings *timings)
  931. {
  932. unsigned long flags;
  933. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  934. spin_lock_irqsave(&data_lock, flags);
  935. if (mp->updating) {
  936. DSSERR("cannot set timings for %s: manager needs to be disabled\n",
  937. mgr->name);
  938. goto out;
  939. }
  940. dss_apply_mgr_timings(mgr, timings);
  941. out:
  942. spin_unlock_irqrestore(&data_lock, flags);
  943. }
  944. static void dss_apply_mgr_lcd_config(struct omap_overlay_manager *mgr,
  945. const struct dss_lcd_mgr_config *config)
  946. {
  947. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  948. mp->lcd_config = *config;
  949. mp->extra_info_dirty = true;
  950. }
  951. static void dss_mgr_set_lcd_config_compat(struct omap_overlay_manager *mgr,
  952. const struct dss_lcd_mgr_config *config)
  953. {
  954. unsigned long flags;
  955. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  956. spin_lock_irqsave(&data_lock, flags);
  957. if (mp->enabled) {
  958. DSSERR("cannot apply lcd config for %s: manager needs to be disabled\n",
  959. mgr->name);
  960. goto out;
  961. }
  962. dss_apply_mgr_lcd_config(mgr, config);
  963. out:
  964. spin_unlock_irqrestore(&data_lock, flags);
  965. }
  966. static int dss_ovl_set_info(struct omap_overlay *ovl,
  967. struct omap_overlay_info *info)
  968. {
  969. struct ovl_priv_data *op = get_ovl_priv(ovl);
  970. unsigned long flags;
  971. int r;
  972. r = dss_ovl_simple_check(ovl, info);
  973. if (r)
  974. return r;
  975. spin_lock_irqsave(&data_lock, flags);
  976. op->user_info = *info;
  977. op->user_info_dirty = true;
  978. spin_unlock_irqrestore(&data_lock, flags);
  979. return 0;
  980. }
  981. static void dss_ovl_get_info(struct omap_overlay *ovl,
  982. struct omap_overlay_info *info)
  983. {
  984. struct ovl_priv_data *op = get_ovl_priv(ovl);
  985. unsigned long flags;
  986. spin_lock_irqsave(&data_lock, flags);
  987. *info = op->user_info;
  988. spin_unlock_irqrestore(&data_lock, flags);
  989. }
  990. static int dss_ovl_set_manager(struct omap_overlay *ovl,
  991. struct omap_overlay_manager *mgr)
  992. {
  993. struct ovl_priv_data *op = get_ovl_priv(ovl);
  994. unsigned long flags;
  995. int r;
  996. if (!mgr)
  997. return -EINVAL;
  998. mutex_lock(&apply_lock);
  999. if (ovl->manager) {
  1000. DSSERR("overlay '%s' already has a manager '%s'\n",
  1001. ovl->name, ovl->manager->name);
  1002. r = -EINVAL;
  1003. goto err;
  1004. }
  1005. r = dispc_runtime_get();
  1006. if (r)
  1007. goto err;
  1008. spin_lock_irqsave(&data_lock, flags);
  1009. if (op->enabled) {
  1010. spin_unlock_irqrestore(&data_lock, flags);
  1011. DSSERR("overlay has to be disabled to change the manager\n");
  1012. r = -EINVAL;
  1013. goto err1;
  1014. }
  1015. dispc_ovl_set_channel_out(ovl->id, mgr->id);
  1016. ovl->manager = mgr;
  1017. list_add_tail(&ovl->list, &mgr->overlays);
  1018. spin_unlock_irqrestore(&data_lock, flags);
  1019. dispc_runtime_put();
  1020. mutex_unlock(&apply_lock);
  1021. return 0;
  1022. err1:
  1023. dispc_runtime_put();
  1024. err:
  1025. mutex_unlock(&apply_lock);
  1026. return r;
  1027. }
  1028. static int dss_ovl_unset_manager(struct omap_overlay *ovl)
  1029. {
  1030. struct ovl_priv_data *op = get_ovl_priv(ovl);
  1031. unsigned long flags;
  1032. int r;
  1033. mutex_lock(&apply_lock);
  1034. if (!ovl->manager) {
  1035. DSSERR("failed to detach overlay: manager not set\n");
  1036. r = -EINVAL;
  1037. goto err;
  1038. }
  1039. spin_lock_irqsave(&data_lock, flags);
  1040. if (op->enabled) {
  1041. spin_unlock_irqrestore(&data_lock, flags);
  1042. DSSERR("overlay has to be disabled to unset the manager\n");
  1043. r = -EINVAL;
  1044. goto err;
  1045. }
  1046. spin_unlock_irqrestore(&data_lock, flags);
  1047. /* wait for pending extra_info updates to ensure the ovl is disabled */
  1048. wait_pending_extra_info_updates();
  1049. /*
  1050. * For a manual update display, there is no guarantee that the overlay
  1051. * is really disabled in HW, we may need an extra update from this
  1052. * manager before the configurations can go in. Return an error if the
  1053. * overlay needed an update from the manager.
  1054. *
  1055. * TODO: Instead of returning an error, try to do a dummy manager update
  1056. * here to disable the overlay in hardware. Use the *GATED fields in
  1057. * the DISPC_CONFIG registers to do a dummy update.
  1058. */
  1059. spin_lock_irqsave(&data_lock, flags);
  1060. if (ovl_manual_update(ovl) && op->extra_info_dirty) {
  1061. spin_unlock_irqrestore(&data_lock, flags);
  1062. DSSERR("need an update to change the manager\n");
  1063. r = -EINVAL;
  1064. goto err;
  1065. }
  1066. ovl->manager = NULL;
  1067. list_del(&ovl->list);
  1068. spin_unlock_irqrestore(&data_lock, flags);
  1069. mutex_unlock(&apply_lock);
  1070. return 0;
  1071. err:
  1072. mutex_unlock(&apply_lock);
  1073. return r;
  1074. }
  1075. static bool dss_ovl_is_enabled(struct omap_overlay *ovl)
  1076. {
  1077. struct ovl_priv_data *op = get_ovl_priv(ovl);
  1078. unsigned long flags;
  1079. bool e;
  1080. spin_lock_irqsave(&data_lock, flags);
  1081. e = op->enabled;
  1082. spin_unlock_irqrestore(&data_lock, flags);
  1083. return e;
  1084. }
  1085. static int dss_ovl_enable(struct omap_overlay *ovl)
  1086. {
  1087. struct ovl_priv_data *op = get_ovl_priv(ovl);
  1088. unsigned long flags;
  1089. int r;
  1090. mutex_lock(&apply_lock);
  1091. if (op->enabled) {
  1092. r = 0;
  1093. goto err1;
  1094. }
  1095. if (ovl->manager == NULL || ovl->manager->output == NULL) {
  1096. r = -EINVAL;
  1097. goto err1;
  1098. }
  1099. spin_lock_irqsave(&data_lock, flags);
  1100. op->enabling = true;
  1101. r = dss_check_settings(ovl->manager);
  1102. if (r) {
  1103. DSSERR("failed to enable overlay %d: check_settings failed\n",
  1104. ovl->id);
  1105. goto err2;
  1106. }
  1107. dss_setup_fifos();
  1108. op->enabling = false;
  1109. dss_apply_ovl_enable(ovl, true);
  1110. dss_write_regs();
  1111. dss_set_go_bits();
  1112. spin_unlock_irqrestore(&data_lock, flags);
  1113. mutex_unlock(&apply_lock);
  1114. return 0;
  1115. err2:
  1116. op->enabling = false;
  1117. spin_unlock_irqrestore(&data_lock, flags);
  1118. err1:
  1119. mutex_unlock(&apply_lock);
  1120. return r;
  1121. }
  1122. static int dss_ovl_disable(struct omap_overlay *ovl)
  1123. {
  1124. struct ovl_priv_data *op = get_ovl_priv(ovl);
  1125. unsigned long flags;
  1126. int r;
  1127. mutex_lock(&apply_lock);
  1128. if (!op->enabled) {
  1129. r = 0;
  1130. goto err;
  1131. }
  1132. if (ovl->manager == NULL || ovl->manager->output == NULL) {
  1133. r = -EINVAL;
  1134. goto err;
  1135. }
  1136. spin_lock_irqsave(&data_lock, flags);
  1137. dss_apply_ovl_enable(ovl, false);
  1138. dss_write_regs();
  1139. dss_set_go_bits();
  1140. spin_unlock_irqrestore(&data_lock, flags);
  1141. mutex_unlock(&apply_lock);
  1142. return 0;
  1143. err:
  1144. mutex_unlock(&apply_lock);
  1145. return r;
  1146. }
  1147. static int dss_mgr_register_framedone_handler_compat(struct omap_overlay_manager *mgr,
  1148. void (*handler)(void *), void *data)
  1149. {
  1150. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  1151. if (mp->framedone_handler)
  1152. return -EBUSY;
  1153. mp->framedone_handler = handler;
  1154. mp->framedone_handler_data = data;
  1155. return 0;
  1156. }
  1157. static void dss_mgr_unregister_framedone_handler_compat(struct omap_overlay_manager *mgr,
  1158. void (*handler)(void *), void *data)
  1159. {
  1160. struct mgr_priv_data *mp = get_mgr_priv(mgr);
  1161. WARN_ON(mp->framedone_handler != handler ||
  1162. mp->framedone_handler_data != data);
  1163. mp->framedone_handler = NULL;
  1164. mp->framedone_handler_data = NULL;
  1165. }
  1166. static const struct dss_mgr_ops apply_mgr_ops = {
  1167. .start_update = dss_mgr_start_update_compat,
  1168. .enable = dss_mgr_enable_compat,
  1169. .disable = dss_mgr_disable_compat,
  1170. .set_timings = dss_mgr_set_timings_compat,
  1171. .set_lcd_config = dss_mgr_set_lcd_config_compat,
  1172. .register_framedone_handler = dss_mgr_register_framedone_handler_compat,
  1173. .unregister_framedone_handler = dss_mgr_unregister_framedone_handler_compat,
  1174. };
  1175. static int compat_refcnt;
  1176. static DEFINE_MUTEX(compat_init_lock);
  1177. int omapdss_compat_init(void)
  1178. {
  1179. struct platform_device *pdev = dss_get_core_pdev();
  1180. struct omap_dss_device *dssdev = NULL;
  1181. int i, r;
  1182. mutex_lock(&compat_init_lock);
  1183. if (compat_refcnt++ > 0)
  1184. goto out;
  1185. apply_init_priv();
  1186. dss_init_overlay_managers(pdev);
  1187. dss_init_overlays(pdev);
  1188. for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) {
  1189. struct omap_overlay_manager *mgr;
  1190. mgr = omap_dss_get_overlay_manager(i);
  1191. mgr->set_output = &dss_mgr_set_output;
  1192. mgr->unset_output = &dss_mgr_unset_output;
  1193. mgr->apply = &omap_dss_mgr_apply;
  1194. mgr->set_manager_info = &dss_mgr_set_info;
  1195. mgr->get_manager_info = &dss_mgr_get_info;
  1196. mgr->wait_for_go = &dss_mgr_wait_for_go;
  1197. mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
  1198. mgr->get_device = &dss_mgr_get_device;
  1199. }
  1200. for (i = 0; i < omap_dss_get_num_overlays(); i++) {
  1201. struct omap_overlay *ovl = omap_dss_get_overlay(i);
  1202. ovl->is_enabled = &dss_ovl_is_enabled;
  1203. ovl->enable = &dss_ovl_enable;
  1204. ovl->disable = &dss_ovl_disable;
  1205. ovl->set_manager = &dss_ovl_set_manager;
  1206. ovl->unset_manager = &dss_ovl_unset_manager;
  1207. ovl->set_overlay_info = &dss_ovl_set_info;
  1208. ovl->get_overlay_info = &dss_ovl_get_info;
  1209. ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
  1210. ovl->get_device = &dss_ovl_get_device;
  1211. }
  1212. r = dss_install_mgr_ops(&apply_mgr_ops);
  1213. if (r)
  1214. goto err_mgr_ops;
  1215. for_each_dss_dev(dssdev) {
  1216. r = display_init_sysfs(pdev, dssdev);
  1217. /* XXX uninit sysfs files on error */
  1218. if (r)
  1219. goto err_disp_sysfs;
  1220. }
  1221. dispc_runtime_get();
  1222. r = dss_dispc_initialize_irq();
  1223. if (r)
  1224. goto err_init_irq;
  1225. dispc_runtime_put();
  1226. out:
  1227. mutex_unlock(&compat_init_lock);
  1228. return 0;
  1229. err_init_irq:
  1230. dispc_runtime_put();
  1231. err_disp_sysfs:
  1232. dss_uninstall_mgr_ops();
  1233. err_mgr_ops:
  1234. dss_uninit_overlay_managers(pdev);
  1235. dss_uninit_overlays(pdev);
  1236. compat_refcnt--;
  1237. mutex_unlock(&compat_init_lock);
  1238. return r;
  1239. }
  1240. EXPORT_SYMBOL(omapdss_compat_init);
  1241. void omapdss_compat_uninit(void)
  1242. {
  1243. struct platform_device *pdev = dss_get_core_pdev();
  1244. struct omap_dss_device *dssdev = NULL;
  1245. mutex_lock(&compat_init_lock);
  1246. if (--compat_refcnt > 0)
  1247. goto out;
  1248. dss_dispc_uninitialize_irq();
  1249. for_each_dss_dev(dssdev)
  1250. display_uninit_sysfs(pdev, dssdev);
  1251. dss_uninstall_mgr_ops();
  1252. dss_uninit_overlay_managers(pdev);
  1253. dss_uninit_overlays(pdev);
  1254. out:
  1255. mutex_unlock(&compat_init_lock);
  1256. }
  1257. EXPORT_SYMBOL(omapdss_compat_uninit);