omap_dmm_tiler.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. /*
  2. * DMM IOMMU driver support functions for TI OMAP processors.
  3. *
  4. * Author: Rob Clark <rob@ti.com>
  5. * Andy Gross <andy.gross@ti.com>
  6. *
  7. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation version 2.
  12. *
  13. * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  14. * kind, whether express or implied; without even the implied warranty
  15. * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. */
  18. #include <linux/completion.h>
  19. #include <linux/delay.h>
  20. #include <linux/dma-mapping.h>
  21. #include <linux/errno.h>
  22. #include <linux/init.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/list.h>
  25. #include <linux/mm.h>
  26. #include <linux/module.h>
  27. #include <linux/platform_device.h> /* platform_device() */
  28. #include <linux/sched.h>
  29. #include <linux/slab.h>
  30. #include <linux/time.h>
  31. #include <linux/vmalloc.h>
  32. #include <linux/wait.h>
  33. #include "omap_dmm_tiler.h"
  34. #include "omap_dmm_priv.h"
  35. #define DMM_DRIVER_NAME "dmm"
  36. /* mappings for associating views to luts */
  37. static struct tcm *containers[TILFMT_NFORMATS];
  38. static struct dmm *omap_dmm;
  39. #if defined(CONFIG_OF)
  40. static const struct of_device_id dmm_of_match[];
  41. #endif
  42. /* global spinlock for protecting lists */
  43. static DEFINE_SPINLOCK(list_lock);
  44. /* Geometry table */
  45. #define GEOM(xshift, yshift, bytes_per_pixel) { \
  46. .x_shft = (xshift), \
  47. .y_shft = (yshift), \
  48. .cpp = (bytes_per_pixel), \
  49. .slot_w = 1 << (SLOT_WIDTH_BITS - (xshift)), \
  50. .slot_h = 1 << (SLOT_HEIGHT_BITS - (yshift)), \
  51. }
  52. static const struct {
  53. uint32_t x_shft; /* unused X-bits (as part of bpp) */
  54. uint32_t y_shft; /* unused Y-bits (as part of bpp) */
  55. uint32_t cpp; /* bytes/chars per pixel */
  56. uint32_t slot_w; /* width of each slot (in pixels) */
  57. uint32_t slot_h; /* height of each slot (in pixels) */
  58. } geom[TILFMT_NFORMATS] = {
  59. [TILFMT_8BIT] = GEOM(0, 0, 1),
  60. [TILFMT_16BIT] = GEOM(0, 1, 2),
  61. [TILFMT_32BIT] = GEOM(1, 1, 4),
  62. [TILFMT_PAGE] = GEOM(SLOT_WIDTH_BITS, SLOT_HEIGHT_BITS, 1),
  63. };
  64. /* lookup table for registers w/ per-engine instances */
  65. static const uint32_t reg[][4] = {
  66. [PAT_STATUS] = {DMM_PAT_STATUS__0, DMM_PAT_STATUS__1,
  67. DMM_PAT_STATUS__2, DMM_PAT_STATUS__3},
  68. [PAT_DESCR] = {DMM_PAT_DESCR__0, DMM_PAT_DESCR__1,
  69. DMM_PAT_DESCR__2, DMM_PAT_DESCR__3},
  70. };
  71. /* simple allocator to grab next 16 byte aligned memory from txn */
  72. static void *alloc_dma(struct dmm_txn *txn, size_t sz, dma_addr_t *pa)
  73. {
  74. void *ptr;
  75. struct refill_engine *engine = txn->engine_handle;
  76. /* dmm programming requires 16 byte aligned addresses */
  77. txn->current_pa = round_up(txn->current_pa, 16);
  78. txn->current_va = (void *)round_up((long)txn->current_va, 16);
  79. ptr = txn->current_va;
  80. *pa = txn->current_pa;
  81. txn->current_pa += sz;
  82. txn->current_va += sz;
  83. BUG_ON((txn->current_va - engine->refill_va) > REFILL_BUFFER_SIZE);
  84. return ptr;
  85. }
  86. /* check status and spin until wait_mask comes true */
  87. static int wait_status(struct refill_engine *engine, uint32_t wait_mask)
  88. {
  89. struct dmm *dmm = engine->dmm;
  90. uint32_t r = 0, err, i;
  91. i = DMM_FIXED_RETRY_COUNT;
  92. while (true) {
  93. r = readl(dmm->base + reg[PAT_STATUS][engine->id]);
  94. err = r & DMM_PATSTATUS_ERR;
  95. if (err)
  96. return -EFAULT;
  97. if ((r & wait_mask) == wait_mask)
  98. break;
  99. if (--i == 0)
  100. return -ETIMEDOUT;
  101. udelay(1);
  102. }
  103. return 0;
  104. }
  105. static void release_engine(struct refill_engine *engine)
  106. {
  107. unsigned long flags;
  108. spin_lock_irqsave(&list_lock, flags);
  109. list_add(&engine->idle_node, &omap_dmm->idle_head);
  110. spin_unlock_irqrestore(&list_lock, flags);
  111. atomic_inc(&omap_dmm->engine_counter);
  112. wake_up_interruptible(&omap_dmm->engine_queue);
  113. }
  114. static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
  115. {
  116. struct dmm *dmm = arg;
  117. uint32_t status = readl(dmm->base + DMM_PAT_IRQSTATUS);
  118. int i;
  119. /* ack IRQ */
  120. writel(status, dmm->base + DMM_PAT_IRQSTATUS);
  121. for (i = 0; i < dmm->num_engines; i++) {
  122. if (status & DMM_IRQSTAT_LST) {
  123. if (dmm->engines[i].async)
  124. release_engine(&dmm->engines[i]);
  125. complete(&dmm->engines[i].compl);
  126. }
  127. status >>= 8;
  128. }
  129. return IRQ_HANDLED;
  130. }
  131. /**
  132. * Get a handle for a DMM transaction
  133. */
  134. static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
  135. {
  136. struct dmm_txn *txn = NULL;
  137. struct refill_engine *engine = NULL;
  138. int ret;
  139. unsigned long flags;
  140. /* wait until an engine is available */
  141. ret = wait_event_interruptible(omap_dmm->engine_queue,
  142. atomic_add_unless(&omap_dmm->engine_counter, -1, 0));
  143. if (ret)
  144. return ERR_PTR(ret);
  145. /* grab an idle engine */
  146. spin_lock_irqsave(&list_lock, flags);
  147. if (!list_empty(&dmm->idle_head)) {
  148. engine = list_entry(dmm->idle_head.next, struct refill_engine,
  149. idle_node);
  150. list_del(&engine->idle_node);
  151. }
  152. spin_unlock_irqrestore(&list_lock, flags);
  153. BUG_ON(!engine);
  154. txn = &engine->txn;
  155. engine->tcm = tcm;
  156. txn->engine_handle = engine;
  157. txn->last_pat = NULL;
  158. txn->current_va = engine->refill_va;
  159. txn->current_pa = engine->refill_pa;
  160. return txn;
  161. }
  162. /**
  163. * Add region to DMM transaction. If pages or pages[i] is NULL, then the
  164. * corresponding slot is cleared (ie. dummy_pa is programmed)
  165. */
  166. static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
  167. struct page **pages, uint32_t npages, uint32_t roll)
  168. {
  169. dma_addr_t pat_pa = 0, data_pa = 0;
  170. uint32_t *data;
  171. struct pat *pat;
  172. struct refill_engine *engine = txn->engine_handle;
  173. int columns = (1 + area->x1 - area->x0);
  174. int rows = (1 + area->y1 - area->y0);
  175. int i = columns*rows;
  176. pat = alloc_dma(txn, sizeof(struct pat), &pat_pa);
  177. if (txn->last_pat)
  178. txn->last_pat->next_pa = (uint32_t)pat_pa;
  179. pat->area = *area;
  180. /* adjust Y coordinates based off of container parameters */
  181. pat->area.y0 += engine->tcm->y_offset;
  182. pat->area.y1 += engine->tcm->y_offset;
  183. pat->ctrl = (struct pat_ctrl){
  184. .start = 1,
  185. .lut_id = engine->tcm->lut_id,
  186. };
  187. data = alloc_dma(txn, 4*i, &data_pa);
  188. /* FIXME: what if data_pa is more than 32-bit ? */
  189. pat->data_pa = data_pa;
  190. while (i--) {
  191. int n = i + roll;
  192. if (n >= npages)
  193. n -= npages;
  194. data[i] = (pages && pages[n]) ?
  195. page_to_phys(pages[n]) : engine->dmm->dummy_pa;
  196. }
  197. txn->last_pat = pat;
  198. return;
  199. }
  200. /**
  201. * Commit the DMM transaction.
  202. */
  203. static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
  204. {
  205. int ret = 0;
  206. struct refill_engine *engine = txn->engine_handle;
  207. struct dmm *dmm = engine->dmm;
  208. if (!txn->last_pat) {
  209. dev_err(engine->dmm->dev, "need at least one txn\n");
  210. ret = -EINVAL;
  211. goto cleanup;
  212. }
  213. txn->last_pat->next_pa = 0;
  214. /* write to PAT_DESCR to clear out any pending transaction */
  215. writel(0x0, dmm->base + reg[PAT_DESCR][engine->id]);
  216. /* wait for engine ready: */
  217. ret = wait_status(engine, DMM_PATSTATUS_READY);
  218. if (ret) {
  219. ret = -EFAULT;
  220. goto cleanup;
  221. }
  222. /* mark whether it is async to denote list management in IRQ handler */
  223. engine->async = wait ? false : true;
  224. reinit_completion(&engine->compl);
  225. /* verify that the irq handler sees the 'async' and completion value */
  226. smp_mb();
  227. /* kick reload */
  228. writel(engine->refill_pa,
  229. dmm->base + reg[PAT_DESCR][engine->id]);
  230. if (wait) {
  231. if (!wait_for_completion_timeout(&engine->compl,
  232. msecs_to_jiffies(100))) {
  233. dev_err(dmm->dev, "timed out waiting for done\n");
  234. ret = -ETIMEDOUT;
  235. }
  236. }
  237. cleanup:
  238. /* only place engine back on list if we are done with it */
  239. if (ret || wait)
  240. release_engine(engine);
  241. return ret;
  242. }
  243. /*
  244. * DMM programming
  245. */
  246. static int fill(struct tcm_area *area, struct page **pages,
  247. uint32_t npages, uint32_t roll, bool wait)
  248. {
  249. int ret = 0;
  250. struct tcm_area slice, area_s;
  251. struct dmm_txn *txn;
  252. txn = dmm_txn_init(omap_dmm, area->tcm);
  253. if (IS_ERR_OR_NULL(txn))
  254. return -ENOMEM;
  255. tcm_for_each_slice(slice, *area, area_s) {
  256. struct pat_area p_area = {
  257. .x0 = slice.p0.x, .y0 = slice.p0.y,
  258. .x1 = slice.p1.x, .y1 = slice.p1.y,
  259. };
  260. dmm_txn_append(txn, &p_area, pages, npages, roll);
  261. roll += tcm_sizeof(slice);
  262. }
  263. ret = dmm_txn_commit(txn, wait);
  264. return ret;
  265. }
  266. /*
  267. * Pin/unpin
  268. */
  269. /* note: slots for which pages[i] == NULL are filled w/ dummy page
  270. */
  271. int tiler_pin(struct tiler_block *block, struct page **pages,
  272. uint32_t npages, uint32_t roll, bool wait)
  273. {
  274. int ret;
  275. ret = fill(&block->area, pages, npages, roll, wait);
  276. if (ret)
  277. tiler_unpin(block);
  278. return ret;
  279. }
  280. int tiler_unpin(struct tiler_block *block)
  281. {
  282. return fill(&block->area, NULL, 0, 0, false);
  283. }
  284. /*
  285. * Reserve/release
  286. */
  287. struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, uint16_t w,
  288. uint16_t h, uint16_t align)
  289. {
  290. struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
  291. u32 min_align = 128;
  292. int ret;
  293. unsigned long flags;
  294. BUG_ON(!validfmt(fmt));
  295. /* convert width/height to slots */
  296. w = DIV_ROUND_UP(w, geom[fmt].slot_w);
  297. h = DIV_ROUND_UP(h, geom[fmt].slot_h);
  298. /* convert alignment to slots */
  299. min_align = max(min_align, (geom[fmt].slot_w * geom[fmt].cpp));
  300. align = ALIGN(align, min_align);
  301. align /= geom[fmt].slot_w * geom[fmt].cpp;
  302. block->fmt = fmt;
  303. ret = tcm_reserve_2d(containers[fmt], w, h, align, &block->area);
  304. if (ret) {
  305. kfree(block);
  306. return ERR_PTR(-ENOMEM);
  307. }
  308. /* add to allocation list */
  309. spin_lock_irqsave(&list_lock, flags);
  310. list_add(&block->alloc_node, &omap_dmm->alloc_head);
  311. spin_unlock_irqrestore(&list_lock, flags);
  312. return block;
  313. }
  314. struct tiler_block *tiler_reserve_1d(size_t size)
  315. {
  316. struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
  317. int num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
  318. unsigned long flags;
  319. if (!block)
  320. return ERR_PTR(-ENOMEM);
  321. block->fmt = TILFMT_PAGE;
  322. if (tcm_reserve_1d(containers[TILFMT_PAGE], num_pages,
  323. &block->area)) {
  324. kfree(block);
  325. return ERR_PTR(-ENOMEM);
  326. }
  327. spin_lock_irqsave(&list_lock, flags);
  328. list_add(&block->alloc_node, &omap_dmm->alloc_head);
  329. spin_unlock_irqrestore(&list_lock, flags);
  330. return block;
  331. }
  332. /* note: if you have pin'd pages, you should have already unpin'd first! */
  333. int tiler_release(struct tiler_block *block)
  334. {
  335. int ret = tcm_free(&block->area);
  336. unsigned long flags;
  337. if (block->area.tcm)
  338. dev_err(omap_dmm->dev, "failed to release block\n");
  339. spin_lock_irqsave(&list_lock, flags);
  340. list_del(&block->alloc_node);
  341. spin_unlock_irqrestore(&list_lock, flags);
  342. kfree(block);
  343. return ret;
  344. }
  345. /*
  346. * Utils
  347. */
  348. /* calculate the tiler space address of a pixel in a view orientation...
  349. * below description copied from the display subsystem section of TRM:
  350. *
  351. * When the TILER is addressed, the bits:
  352. * [28:27] = 0x0 for 8-bit tiled
  353. * 0x1 for 16-bit tiled
  354. * 0x2 for 32-bit tiled
  355. * 0x3 for page mode
  356. * [31:29] = 0x0 for 0-degree view
  357. * 0x1 for 180-degree view + mirroring
  358. * 0x2 for 0-degree view + mirroring
  359. * 0x3 for 180-degree view
  360. * 0x4 for 270-degree view + mirroring
  361. * 0x5 for 270-degree view
  362. * 0x6 for 90-degree view
  363. * 0x7 for 90-degree view + mirroring
  364. * Otherwise the bits indicated the corresponding bit address to access
  365. * the SDRAM.
  366. */
  367. static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y)
  368. {
  369. u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment;
  370. x_bits = CONT_WIDTH_BITS - geom[fmt].x_shft;
  371. y_bits = CONT_HEIGHT_BITS - geom[fmt].y_shft;
  372. alignment = geom[fmt].x_shft + geom[fmt].y_shft;
  373. /* validate coordinate */
  374. x_mask = MASK(x_bits);
  375. y_mask = MASK(y_bits);
  376. if (x < 0 || x > x_mask || y < 0 || y > y_mask) {
  377. DBG("invalid coords: %u < 0 || %u > %u || %u < 0 || %u > %u",
  378. x, x, x_mask, y, y, y_mask);
  379. return 0;
  380. }
  381. /* account for mirroring */
  382. if (orient & MASK_X_INVERT)
  383. x ^= x_mask;
  384. if (orient & MASK_Y_INVERT)
  385. y ^= y_mask;
  386. /* get coordinate address */
  387. if (orient & MASK_XY_FLIP)
  388. tmp = ((x << y_bits) + y);
  389. else
  390. tmp = ((y << x_bits) + x);
  391. return TIL_ADDR((tmp << alignment), orient, fmt);
  392. }
  393. dma_addr_t tiler_ssptr(struct tiler_block *block)
  394. {
  395. BUG_ON(!validfmt(block->fmt));
  396. return TILVIEW_8BIT + tiler_get_address(block->fmt, 0,
  397. block->area.p0.x * geom[block->fmt].slot_w,
  398. block->area.p0.y * geom[block->fmt].slot_h);
  399. }
  400. dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient,
  401. uint32_t x, uint32_t y)
  402. {
  403. struct tcm_pt *p = &block->area.p0;
  404. BUG_ON(!validfmt(block->fmt));
  405. return tiler_get_address(block->fmt, orient,
  406. (p->x * geom[block->fmt].slot_w) + x,
  407. (p->y * geom[block->fmt].slot_h) + y);
  408. }
  409. void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h)
  410. {
  411. BUG_ON(!validfmt(fmt));
  412. *w = round_up(*w, geom[fmt].slot_w);
  413. *h = round_up(*h, geom[fmt].slot_h);
  414. }
  415. uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient)
  416. {
  417. BUG_ON(!validfmt(fmt));
  418. if (orient & MASK_XY_FLIP)
  419. return 1 << (CONT_HEIGHT_BITS + geom[fmt].x_shft);
  420. else
  421. return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
  422. }
  423. size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h)
  424. {
  425. tiler_align(fmt, &w, &h);
  426. return geom[fmt].cpp * w * h;
  427. }
  428. size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h)
  429. {
  430. BUG_ON(!validfmt(fmt));
  431. return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h;
  432. }
  433. uint32_t tiler_get_cpu_cache_flags(void)
  434. {
  435. return omap_dmm->plat_data->cpu_cache_flags;
  436. }
  437. bool dmm_is_available(void)
  438. {
  439. return omap_dmm ? true : false;
  440. }
  441. static int omap_dmm_remove(struct platform_device *dev)
  442. {
  443. struct tiler_block *block, *_block;
  444. int i;
  445. unsigned long flags;
  446. if (omap_dmm) {
  447. /* free all area regions */
  448. spin_lock_irqsave(&list_lock, flags);
  449. list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head,
  450. alloc_node) {
  451. list_del(&block->alloc_node);
  452. kfree(block);
  453. }
  454. spin_unlock_irqrestore(&list_lock, flags);
  455. for (i = 0; i < omap_dmm->num_lut; i++)
  456. if (omap_dmm->tcm && omap_dmm->tcm[i])
  457. omap_dmm->tcm[i]->deinit(omap_dmm->tcm[i]);
  458. kfree(omap_dmm->tcm);
  459. kfree(omap_dmm->engines);
  460. if (omap_dmm->refill_va)
  461. dma_free_writecombine(omap_dmm->dev,
  462. REFILL_BUFFER_SIZE * omap_dmm->num_engines,
  463. omap_dmm->refill_va,
  464. omap_dmm->refill_pa);
  465. if (omap_dmm->dummy_page)
  466. __free_page(omap_dmm->dummy_page);
  467. if (omap_dmm->irq > 0)
  468. free_irq(omap_dmm->irq, omap_dmm);
  469. iounmap(omap_dmm->base);
  470. kfree(omap_dmm);
  471. omap_dmm = NULL;
  472. }
  473. return 0;
  474. }
  475. static int omap_dmm_probe(struct platform_device *dev)
  476. {
  477. int ret = -EFAULT, i;
  478. struct tcm_area area = {0};
  479. u32 hwinfo, pat_geom;
  480. struct resource *mem;
  481. omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL);
  482. if (!omap_dmm)
  483. goto fail;
  484. /* initialize lists */
  485. INIT_LIST_HEAD(&omap_dmm->alloc_head);
  486. INIT_LIST_HEAD(&omap_dmm->idle_head);
  487. init_waitqueue_head(&omap_dmm->engine_queue);
  488. if (dev->dev.of_node) {
  489. const struct of_device_id *match;
  490. match = of_match_node(dmm_of_match, dev->dev.of_node);
  491. if (!match) {
  492. dev_err(&dev->dev, "failed to find matching device node\n");
  493. return -ENODEV;
  494. }
  495. omap_dmm->plat_data = match->data;
  496. }
  497. /* lookup hwmod data - base address and irq */
  498. mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
  499. if (!mem) {
  500. dev_err(&dev->dev, "failed to get base address resource\n");
  501. goto fail;
  502. }
  503. omap_dmm->base = ioremap(mem->start, SZ_2K);
  504. if (!omap_dmm->base) {
  505. dev_err(&dev->dev, "failed to get dmm base address\n");
  506. goto fail;
  507. }
  508. omap_dmm->irq = platform_get_irq(dev, 0);
  509. if (omap_dmm->irq < 0) {
  510. dev_err(&dev->dev, "failed to get IRQ resource\n");
  511. goto fail;
  512. }
  513. omap_dmm->dev = &dev->dev;
  514. hwinfo = readl(omap_dmm->base + DMM_PAT_HWINFO);
  515. omap_dmm->num_engines = (hwinfo >> 24) & 0x1F;
  516. omap_dmm->num_lut = (hwinfo >> 16) & 0x1F;
  517. omap_dmm->container_width = 256;
  518. omap_dmm->container_height = 128;
  519. atomic_set(&omap_dmm->engine_counter, omap_dmm->num_engines);
  520. /* read out actual LUT width and height */
  521. pat_geom = readl(omap_dmm->base + DMM_PAT_GEOMETRY);
  522. omap_dmm->lut_width = ((pat_geom >> 16) & 0xF) << 5;
  523. omap_dmm->lut_height = ((pat_geom >> 24) & 0xF) << 5;
  524. /* increment LUT by one if on OMAP5 */
  525. /* LUT has twice the height, and is split into a separate container */
  526. if (omap_dmm->lut_height != omap_dmm->container_height)
  527. omap_dmm->num_lut++;
  528. /* initialize DMM registers */
  529. writel(0x88888888, omap_dmm->base + DMM_PAT_VIEW__0);
  530. writel(0x88888888, omap_dmm->base + DMM_PAT_VIEW__1);
  531. writel(0x80808080, omap_dmm->base + DMM_PAT_VIEW_MAP__0);
  532. writel(0x80000000, omap_dmm->base + DMM_PAT_VIEW_MAP_BASE);
  533. writel(0x88888888, omap_dmm->base + DMM_TILER_OR__0);
  534. writel(0x88888888, omap_dmm->base + DMM_TILER_OR__1);
  535. ret = request_irq(omap_dmm->irq, omap_dmm_irq_handler, IRQF_SHARED,
  536. "omap_dmm_irq_handler", omap_dmm);
  537. if (ret) {
  538. dev_err(&dev->dev, "couldn't register IRQ %d, error %d\n",
  539. omap_dmm->irq, ret);
  540. omap_dmm->irq = -1;
  541. goto fail;
  542. }
  543. /* Enable all interrupts for each refill engine except
  544. * ERR_LUT_MISS<n> (which is just advisory, and we don't care
  545. * about because we want to be able to refill live scanout
  546. * buffers for accelerated pan/scroll) and FILL_DSC<n> which
  547. * we just generally don't care about.
  548. */
  549. writel(0x7e7e7e7e, omap_dmm->base + DMM_PAT_IRQENABLE_SET);
  550. omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
  551. if (!omap_dmm->dummy_page) {
  552. dev_err(&dev->dev, "could not allocate dummy page\n");
  553. ret = -ENOMEM;
  554. goto fail;
  555. }
  556. /* set dma mask for device */
  557. ret = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32));
  558. if (ret)
  559. goto fail;
  560. omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
  561. /* alloc refill memory */
  562. omap_dmm->refill_va = dma_alloc_writecombine(&dev->dev,
  563. REFILL_BUFFER_SIZE * omap_dmm->num_engines,
  564. &omap_dmm->refill_pa, GFP_KERNEL);
  565. if (!omap_dmm->refill_va) {
  566. dev_err(&dev->dev, "could not allocate refill memory\n");
  567. goto fail;
  568. }
  569. /* alloc engines */
  570. omap_dmm->engines = kcalloc(omap_dmm->num_engines,
  571. sizeof(struct refill_engine), GFP_KERNEL);
  572. if (!omap_dmm->engines) {
  573. ret = -ENOMEM;
  574. goto fail;
  575. }
  576. for (i = 0; i < omap_dmm->num_engines; i++) {
  577. omap_dmm->engines[i].id = i;
  578. omap_dmm->engines[i].dmm = omap_dmm;
  579. omap_dmm->engines[i].refill_va = omap_dmm->refill_va +
  580. (REFILL_BUFFER_SIZE * i);
  581. omap_dmm->engines[i].refill_pa = omap_dmm->refill_pa +
  582. (REFILL_BUFFER_SIZE * i);
  583. init_completion(&omap_dmm->engines[i].compl);
  584. list_add(&omap_dmm->engines[i].idle_node, &omap_dmm->idle_head);
  585. }
  586. omap_dmm->tcm = kcalloc(omap_dmm->num_lut, sizeof(*omap_dmm->tcm),
  587. GFP_KERNEL);
  588. if (!omap_dmm->tcm) {
  589. ret = -ENOMEM;
  590. goto fail;
  591. }
  592. /* init containers */
  593. /* Each LUT is associated with a TCM (container manager). We use the
  594. lut_id to denote the lut_id used to identify the correct LUT for
  595. programming during reill operations */
  596. for (i = 0; i < omap_dmm->num_lut; i++) {
  597. omap_dmm->tcm[i] = sita_init(omap_dmm->container_width,
  598. omap_dmm->container_height,
  599. NULL);
  600. if (!omap_dmm->tcm[i]) {
  601. dev_err(&dev->dev, "failed to allocate container\n");
  602. ret = -ENOMEM;
  603. goto fail;
  604. }
  605. omap_dmm->tcm[i]->lut_id = i;
  606. }
  607. /* assign access mode containers to applicable tcm container */
  608. /* OMAP 4 has 1 container for all 4 views */
  609. /* OMAP 5 has 2 containers, 1 for 2D and 1 for 1D */
  610. containers[TILFMT_8BIT] = omap_dmm->tcm[0];
  611. containers[TILFMT_16BIT] = omap_dmm->tcm[0];
  612. containers[TILFMT_32BIT] = omap_dmm->tcm[0];
  613. if (omap_dmm->container_height != omap_dmm->lut_height) {
  614. /* second LUT is used for PAGE mode. Programming must use
  615. y offset that is added to all y coordinates. LUT id is still
  616. 0, because it is the same LUT, just the upper 128 lines */
  617. containers[TILFMT_PAGE] = omap_dmm->tcm[1];
  618. omap_dmm->tcm[1]->y_offset = OMAP5_LUT_OFFSET;
  619. omap_dmm->tcm[1]->lut_id = 0;
  620. } else {
  621. containers[TILFMT_PAGE] = omap_dmm->tcm[0];
  622. }
  623. area = (struct tcm_area) {
  624. .tcm = NULL,
  625. .p1.x = omap_dmm->container_width - 1,
  626. .p1.y = omap_dmm->container_height - 1,
  627. };
  628. /* initialize all LUTs to dummy page entries */
  629. for (i = 0; i < omap_dmm->num_lut; i++) {
  630. area.tcm = omap_dmm->tcm[i];
  631. if (fill(&area, NULL, 0, 0, true))
  632. dev_err(omap_dmm->dev, "refill failed");
  633. }
  634. dev_info(omap_dmm->dev, "initialized all PAT entries\n");
  635. return 0;
  636. fail:
  637. if (omap_dmm_remove(dev))
  638. dev_err(&dev->dev, "cleanup failed\n");
  639. return ret;
  640. }
  641. /*
  642. * debugfs support
  643. */
  644. #ifdef CONFIG_DEBUG_FS
  645. static const char *alphabet = "abcdefghijklmnopqrstuvwxyz"
  646. "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  647. static const char *special = ".,:;'\"`~!^-+";
  648. static void fill_map(char **map, int xdiv, int ydiv, struct tcm_area *a,
  649. char c, bool ovw)
  650. {
  651. int x, y;
  652. for (y = a->p0.y / ydiv; y <= a->p1.y / ydiv; y++)
  653. for (x = a->p0.x / xdiv; x <= a->p1.x / xdiv; x++)
  654. if (map[y][x] == ' ' || ovw)
  655. map[y][x] = c;
  656. }
  657. static void fill_map_pt(char **map, int xdiv, int ydiv, struct tcm_pt *p,
  658. char c)
  659. {
  660. map[p->y / ydiv][p->x / xdiv] = c;
  661. }
  662. static char read_map_pt(char **map, int xdiv, int ydiv, struct tcm_pt *p)
  663. {
  664. return map[p->y / ydiv][p->x / xdiv];
  665. }
  666. static int map_width(int xdiv, int x0, int x1)
  667. {
  668. return (x1 / xdiv) - (x0 / xdiv) + 1;
  669. }
  670. static void text_map(char **map, int xdiv, char *nice, int yd, int x0, int x1)
  671. {
  672. char *p = map[yd] + (x0 / xdiv);
  673. int w = (map_width(xdiv, x0, x1) - strlen(nice)) / 2;
  674. if (w >= 0) {
  675. p += w;
  676. while (*nice)
  677. *p++ = *nice++;
  678. }
  679. }
  680. static void map_1d_info(char **map, int xdiv, int ydiv, char *nice,
  681. struct tcm_area *a)
  682. {
  683. sprintf(nice, "%dK", tcm_sizeof(*a) * 4);
  684. if (a->p0.y + 1 < a->p1.y) {
  685. text_map(map, xdiv, nice, (a->p0.y + a->p1.y) / 2 / ydiv, 0,
  686. 256 - 1);
  687. } else if (a->p0.y < a->p1.y) {
  688. if (strlen(nice) < map_width(xdiv, a->p0.x, 256 - 1))
  689. text_map(map, xdiv, nice, a->p0.y / ydiv,
  690. a->p0.x + xdiv, 256 - 1);
  691. else if (strlen(nice) < map_width(xdiv, 0, a->p1.x))
  692. text_map(map, xdiv, nice, a->p1.y / ydiv,
  693. 0, a->p1.y - xdiv);
  694. } else if (strlen(nice) + 1 < map_width(xdiv, a->p0.x, a->p1.x)) {
  695. text_map(map, xdiv, nice, a->p0.y / ydiv, a->p0.x, a->p1.x);
  696. }
  697. }
  698. static void map_2d_info(char **map, int xdiv, int ydiv, char *nice,
  699. struct tcm_area *a)
  700. {
  701. sprintf(nice, "(%d*%d)", tcm_awidth(*a), tcm_aheight(*a));
  702. if (strlen(nice) + 1 < map_width(xdiv, a->p0.x, a->p1.x))
  703. text_map(map, xdiv, nice, (a->p0.y + a->p1.y) / 2 / ydiv,
  704. a->p0.x, a->p1.x);
  705. }
  706. int tiler_map_show(struct seq_file *s, void *arg)
  707. {
  708. int xdiv = 2, ydiv = 1;
  709. char **map = NULL, *global_map;
  710. struct tiler_block *block;
  711. struct tcm_area a, p;
  712. int i;
  713. const char *m2d = alphabet;
  714. const char *a2d = special;
  715. const char *m2dp = m2d, *a2dp = a2d;
  716. char nice[128];
  717. int h_adj;
  718. int w_adj;
  719. unsigned long flags;
  720. int lut_idx;
  721. if (!omap_dmm) {
  722. /* early return if dmm/tiler device is not initialized */
  723. return 0;
  724. }
  725. h_adj = omap_dmm->container_height / ydiv;
  726. w_adj = omap_dmm->container_width / xdiv;
  727. map = kmalloc(h_adj * sizeof(*map), GFP_KERNEL);
  728. global_map = kmalloc((w_adj + 1) * h_adj, GFP_KERNEL);
  729. if (!map || !global_map)
  730. goto error;
  731. for (lut_idx = 0; lut_idx < omap_dmm->num_lut; lut_idx++) {
  732. memset(map, 0, h_adj * sizeof(*map));
  733. memset(global_map, ' ', (w_adj + 1) * h_adj);
  734. for (i = 0; i < omap_dmm->container_height; i++) {
  735. map[i] = global_map + i * (w_adj + 1);
  736. map[i][w_adj] = 0;
  737. }
  738. spin_lock_irqsave(&list_lock, flags);
  739. list_for_each_entry(block, &omap_dmm->alloc_head, alloc_node) {
  740. if (block->area.tcm == omap_dmm->tcm[lut_idx]) {
  741. if (block->fmt != TILFMT_PAGE) {
  742. fill_map(map, xdiv, ydiv, &block->area,
  743. *m2dp, true);
  744. if (!*++a2dp)
  745. a2dp = a2d;
  746. if (!*++m2dp)
  747. m2dp = m2d;
  748. map_2d_info(map, xdiv, ydiv, nice,
  749. &block->area);
  750. } else {
  751. bool start = read_map_pt(map, xdiv,
  752. ydiv, &block->area.p0) == ' ';
  753. bool end = read_map_pt(map, xdiv, ydiv,
  754. &block->area.p1) == ' ';
  755. tcm_for_each_slice(a, block->area, p)
  756. fill_map(map, xdiv, ydiv, &a,
  757. '=', true);
  758. fill_map_pt(map, xdiv, ydiv,
  759. &block->area.p0,
  760. start ? '<' : 'X');
  761. fill_map_pt(map, xdiv, ydiv,
  762. &block->area.p1,
  763. end ? '>' : 'X');
  764. map_1d_info(map, xdiv, ydiv, nice,
  765. &block->area);
  766. }
  767. }
  768. }
  769. spin_unlock_irqrestore(&list_lock, flags);
  770. if (s) {
  771. seq_printf(s, "CONTAINER %d DUMP BEGIN\n", lut_idx);
  772. for (i = 0; i < 128; i++)
  773. seq_printf(s, "%03d:%s\n", i, map[i]);
  774. seq_printf(s, "CONTAINER %d DUMP END\n", lut_idx);
  775. } else {
  776. dev_dbg(omap_dmm->dev, "CONTAINER %d DUMP BEGIN\n",
  777. lut_idx);
  778. for (i = 0; i < 128; i++)
  779. dev_dbg(omap_dmm->dev, "%03d:%s\n", i, map[i]);
  780. dev_dbg(omap_dmm->dev, "CONTAINER %d DUMP END\n",
  781. lut_idx);
  782. }
  783. }
  784. error:
  785. kfree(map);
  786. kfree(global_map);
  787. return 0;
  788. }
  789. #endif
  790. #ifdef CONFIG_PM_SLEEP
  791. static int omap_dmm_resume(struct device *dev)
  792. {
  793. struct tcm_area area;
  794. int i;
  795. if (!omap_dmm)
  796. return -ENODEV;
  797. area = (struct tcm_area) {
  798. .tcm = NULL,
  799. .p1.x = omap_dmm->container_width - 1,
  800. .p1.y = omap_dmm->container_height - 1,
  801. };
  802. /* initialize all LUTs to dummy page entries */
  803. for (i = 0; i < omap_dmm->num_lut; i++) {
  804. area.tcm = omap_dmm->tcm[i];
  805. if (fill(&area, NULL, 0, 0, true))
  806. dev_err(dev, "refill failed");
  807. }
  808. return 0;
  809. }
  810. #endif
  811. static SIMPLE_DEV_PM_OPS(omap_dmm_pm_ops, NULL, omap_dmm_resume);
  812. #if defined(CONFIG_OF)
  813. static const struct dmm_platform_data dmm_omap4_platform_data = {
  814. .cpu_cache_flags = OMAP_BO_WC,
  815. };
  816. static const struct dmm_platform_data dmm_omap5_platform_data = {
  817. .cpu_cache_flags = OMAP_BO_UNCACHED,
  818. };
  819. static const struct of_device_id dmm_of_match[] = {
  820. {
  821. .compatible = "ti,omap4-dmm",
  822. .data = &dmm_omap4_platform_data,
  823. },
  824. {
  825. .compatible = "ti,omap5-dmm",
  826. .data = &dmm_omap5_platform_data,
  827. },
  828. {},
  829. };
  830. #endif
  831. struct platform_driver omap_dmm_driver = {
  832. .probe = omap_dmm_probe,
  833. .remove = omap_dmm_remove,
  834. .driver = {
  835. .owner = THIS_MODULE,
  836. .name = DMM_DRIVER_NAME,
  837. .of_match_table = of_match_ptr(dmm_of_match),
  838. .pm = &omap_dmm_pm_ops,
  839. },
  840. };
  841. MODULE_LICENSE("GPL v2");
  842. MODULE_AUTHOR("Andy Gross <andy.gross@ti.com>");
  843. MODULE_DESCRIPTION("OMAP DMM/Tiler Driver");
  844. MODULE_ALIAS("platform:" DMM_DRIVER_NAME);