File Index
Files and directories
Sign in
FILE

omap_dmm_tiler.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * DMM IOMMU driver support functions for TI OMAP processors.
   4 *
   5 * Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
   6 * Author: Rob Clark <rob@ti.com>
   7 *         Andy Gross <andy.gross@ti.com>
   8 */
   9
  10#include <linux/completion.h>
  11#include <linux/delay.h>
  12#include <linux/dma-mapping.h>
  13#include <linux/dmaengine.h>
  14#include <linux/errno.h>
  15#include <linux/init.h>
  16#include <linux/interrupt.h>
  17#include <linux/list.h>
  18#include <linux/mm.h>
  19#include <linux/module.h>
  20#include <linux/of.h>
  21#include <linux/platform_device.h> /* platform_device() */
  22#include <linux/sched.h>
  23#include <linux/seq_file.h>
  24#include <linux/slab.h>
  25#include <linux/time.h>
  26#include <linux/vmalloc.h>
  27#include <linux/wait.h>
  28
  29#include <drm/drm_print.h>
  30
  31#include "omap_dmm_tiler.h"
  32#include "omap_dmm_priv.h"
  33
  34#define DMM_DRIVER_NAME "dmm"
  35
  36/* mappings for associating views to luts */
  37static struct tcm *containers[TILFMT_NFORMATS];
  38static struct dmm *omap_dmm;
  39
  40#if defined(CONFIG_OF)
  41static const struct of_device_id dmm_of_match[];
  42#endif
  43
  44/* global spinlock for protecting lists */
  45static DEFINE_SPINLOCK(list_lock);
  46
  47/* Geometry table */
  48#define GEOM(xshift, yshift, bytes_per_pixel) { \
  49		.x_shft = (xshift), \
  50		.y_shft = (yshift), \
  51		.cpp    = (bytes_per_pixel), \
  52		.slot_w = 1 << (SLOT_WIDTH_BITS - (xshift)), \
  53		.slot_h = 1 << (SLOT_HEIGHT_BITS - (yshift)), \
  54	}
  55
  56static const struct {
  57	u32 x_shft;	/* unused X-bits (as part of bpp) */
  58	u32 y_shft;	/* unused Y-bits (as part of bpp) */
  59	u32 cpp;		/* bytes/chars per pixel */
  60	u32 slot_w;	/* width of each slot (in pixels) */
  61	u32 slot_h;	/* height of each slot (in pixels) */
  62} geom[TILFMT_NFORMATS] = {
  63	[TILFMT_8BIT]  = GEOM(0, 0, 1),
  64	[TILFMT_16BIT] = GEOM(0, 1, 2),
  65	[TILFMT_32BIT] = GEOM(1, 1, 4),
  66	[TILFMT_PAGE]  = GEOM(SLOT_WIDTH_BITS, SLOT_HEIGHT_BITS, 1),
  67};
  68
  69
  70/* lookup table for registers w/ per-engine instances */
  71static const u32 reg[][4] = {
  72	[PAT_STATUS] = {DMM_PAT_STATUS__0, DMM_PAT_STATUS__1,
  73			DMM_PAT_STATUS__2, DMM_PAT_STATUS__3},
  74	[PAT_DESCR]  = {DMM_PAT_DESCR__0, DMM_PAT_DESCR__1,
  75			DMM_PAT_DESCR__2, DMM_PAT_DESCR__3},
  76};
  77
  78static int dmm_dma_copy(struct dmm *dmm, dma_addr_t src, dma_addr_t dst)
  79{
  80	struct dma_async_tx_descriptor *tx;
  81	enum dma_status status;
  82	dma_cookie_t cookie;
  83
  84	tx = dmaengine_prep_dma_memcpy(dmm->wa_dma_chan, dst, src, 4, 0);
  85	if (!tx) {
  86		dev_err(dmm->dev, "Failed to prepare DMA memcpy\n");
  87		return -EIO;
  88	}
  89
  90	cookie = tx->tx_submit(tx);
  91	if (dma_submit_error(cookie)) {
  92		dev_err(dmm->dev, "Failed to do DMA tx_submit\n");
  93		return -EIO;
  94	}
  95
  96	status = dma_sync_wait(dmm->wa_dma_chan, cookie);
  97	if (status != DMA_COMPLETE)
  98		dev_err(dmm->dev, "i878 wa DMA copy failure\n");
  99
 100	dmaengine_terminate_all(dmm->wa_dma_chan);
 101	return 0;
 102}
 103
 104static u32 dmm_read_wa(struct dmm *dmm, u32 reg)
 105{
 106	dma_addr_t src, dst;
 107	int r;
 108
 109	src = dmm->phys_base + reg;
 110	dst = dmm->wa_dma_handle;
 111
 112	r = dmm_dma_copy(dmm, src, dst);
 113	if (r) {
 114		dev_err(dmm->dev, "sDMA read transfer timeout\n");
 115		return readl(dmm->base + reg);
 116	}
 117
 118	/*
 119	 * As per i878 workaround, the DMA is used to access the DMM registers.
 120	 * Make sure that the readl is not moved by the compiler or the CPU
 121	 * earlier than the DMA finished writing the value to memory.
 122	 */
 123	rmb();
 124	return readl((__iomem void *)dmm->wa_dma_data);
 125}
 126
 127static void dmm_write_wa(struct dmm *dmm, u32 val, u32 reg)
 128{
 129	dma_addr_t src, dst;
 130	int r;
 131
 132	writel(val, (__iomem void *)dmm->wa_dma_data);
 133	/*
 134	 * As per i878 workaround, the DMA is used to access the DMM registers.
 135	 * Make sure that the writel is not moved by the compiler or the CPU, so
 136	 * the data will be in place before we start the DMA to do the actual
 137	 * register write.
 138	 */
 139	wmb();
 140
 141	src = dmm->wa_dma_handle;
 142	dst = dmm->phys_base + reg;
 143
 144	r = dmm_dma_copy(dmm, src, dst);
 145	if (r) {
 146		dev_err(dmm->dev, "sDMA write transfer timeout\n");
 147		writel(val, dmm->base + reg);
 148	}
 149}
 150
 151static u32 dmm_read(struct dmm *dmm, u32 reg)
 152{
 153	if (dmm->dmm_workaround) {
 154		u32 v;
 155		unsigned long flags;
 156
 157		spin_lock_irqsave(&dmm->wa_lock, flags);
 158		v = dmm_read_wa(dmm, reg);
 159		spin_unlock_irqrestore(&dmm->wa_lock, flags);
 160
 161		return v;
 162	} else {
 163		return readl(dmm->base + reg);
 164	}
 165}
 166
 167static void dmm_write(struct dmm *dmm, u32 val, u32 reg)
 168{
 169	if (dmm->dmm_workaround) {
 170		unsigned long flags;
 171
 172		spin_lock_irqsave(&dmm->wa_lock, flags);
 173		dmm_write_wa(dmm, val, reg);
 174		spin_unlock_irqrestore(&dmm->wa_lock, flags);
 175	} else {
 176		writel(val, dmm->base + reg);
 177	}
 178}
 179
 180static int dmm_workaround_init(struct dmm *dmm)
 181{
 182	dma_cap_mask_t mask;
 183
 184	spin_lock_init(&dmm->wa_lock);
 185
 186	dmm->wa_dma_data = dma_alloc_coherent(dmm->dev,  sizeof(u32),
 187					      &dmm->wa_dma_handle, GFP_KERNEL);
 188	if (!dmm->wa_dma_data)
 189		return -ENOMEM;
 190
 191	dma_cap_zero(mask);
 192	dma_cap_set(DMA_MEMCPY, mask);
 193
 194	dmm->wa_dma_chan = dma_request_channel(mask, NULL, NULL);
 195	if (!dmm->wa_dma_chan) {
 196		dma_free_coherent(dmm->dev, 4, dmm->wa_dma_data, dmm->wa_dma_handle);
 197		return -ENODEV;
 198	}
 199
 200	return 0;
 201}
 202
 203static void dmm_workaround_uninit(struct dmm *dmm)
 204{
 205	dma_release_channel(dmm->wa_dma_chan);
 206
 207	dma_free_coherent(dmm->dev, 4, dmm->wa_dma_data, dmm->wa_dma_handle);
 208}
 209
 210/* simple allocator to grab next 16 byte aligned memory from txn */
 211static void *alloc_dma(struct dmm_txn *txn, size_t sz, dma_addr_t *pa)
 212{
 213	void *ptr;
 214	struct refill_engine *engine = txn->engine_handle;
 215
 216	/* dmm programming requires 16 byte aligned addresses */
 217	txn->current_pa = round_up(txn->current_pa, 16);
 218	txn->current_va = (void *)round_up((long)txn->current_va, 16);
 219
 220	ptr = txn->current_va;
 221	*pa = txn->current_pa;
 222
 223	txn->current_pa += sz;
 224	txn->current_va += sz;
 225
 226	BUG_ON((txn->current_va - engine->refill_va) > REFILL_BUFFER_SIZE);
 227
 228	return ptr;
 229}
 230
 231/* check status and spin until wait_mask comes true */
 232static int wait_status(struct refill_engine *engine, u32 wait_mask)
 233{
 234	struct dmm *dmm = engine->dmm;
 235	u32 r = 0, err, i;
 236
 237	i = DMM_FIXED_RETRY_COUNT;
 238	while (true) {
 239		r = dmm_read(dmm, reg[PAT_STATUS][engine->id]);
 240		err = r & DMM_PATSTATUS_ERR;
 241		if (err) {
 242			dev_err(dmm->dev,
 243				"%s: error (engine%d). PAT_STATUS: 0x%08x\n",
 244				__func__, engine->id, r);
 245			return -EFAULT;
 246		}
 247
 248		if ((r & wait_mask) == wait_mask)
 249			break;
 250
 251		if (--i == 0) {
 252			dev_err(dmm->dev,
 253				"%s: timeout (engine%d). PAT_STATUS: 0x%08x\n",
 254				__func__, engine->id, r);
 255			return -ETIMEDOUT;
 256		}
 257
 258		udelay(1);
 259	}
 260
 261	return 0;
 262}
 263
 264static void release_engine(struct refill_engine *engine)
 265{
 266	unsigned long flags;
 267
 268	spin_lock_irqsave(&list_lock, flags);
 269	list_add(&engine->idle_node, &omap_dmm->idle_head);
 270	spin_unlock_irqrestore(&list_lock, flags);
 271
 272	atomic_inc(&omap_dmm->engine_counter);
 273	wake_up_interruptible(&omap_dmm->engine_queue);
 274}
 275
 276static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
 277{
 278	struct dmm *dmm = arg;
 279	u32 status = dmm_read(dmm, DMM_PAT_IRQSTATUS);
 280	int i;
 281
 282	/* ack IRQ */
 283	dmm_write(dmm, status, DMM_PAT_IRQSTATUS);
 284
 285	for (i = 0; i < dmm->num_engines; i++) {
 286		if (status & DMM_IRQSTAT_ERR_MASK)
 287			dev_err(dmm->dev,
 288				"irq error(engine%d): IRQSTAT 0x%02x\n",
 289				i, status & 0xff);
 290
 291		if (status & DMM_IRQSTAT_LST) {
 292			if (dmm->engines[i].async)
 293				release_engine(&dmm->engines[i]);
 294
 295			complete(&dmm->engines[i].compl);
 296		}
 297
 298		status >>= 8;
 299	}
 300
 301	return IRQ_HANDLED;
 302}
 303
 304/*
 305 * Get a handle for a DMM transaction
 306 */
 307static struct dmm_txn *dmm_txn_init(struct dmm *dmm, struct tcm *tcm)
 308{
 309	struct dmm_txn *txn = NULL;
 310	struct refill_engine *engine = NULL;
 311	int ret;
 312	unsigned long flags;
 313
 314
 315	/* wait until an engine is available */
 316	ret = wait_event_interruptible(omap_dmm->engine_queue,
 317		atomic_add_unless(&omap_dmm->engine_counter, -1, 0));
 318	if (ret)
 319		return ERR_PTR(ret);
 320
 321	/* grab an idle engine */
 322	spin_lock_irqsave(&list_lock, flags);
 323	if (!list_empty(&dmm->idle_head)) {
 324		engine = list_entry(dmm->idle_head.next, struct refill_engine,
 325					idle_node);
 326		list_del(&engine->idle_node);
 327	}
 328	spin_unlock_irqrestore(&list_lock, flags);
 329
 330	BUG_ON(!engine);
 331
 332	txn = &engine->txn;
 333	engine->tcm = tcm;
 334	txn->engine_handle = engine;
 335	txn->last_pat = NULL;
 336	txn->current_va = engine->refill_va;
 337	txn->current_pa = engine->refill_pa;
 338
 339	return txn;
 340}
 341
 342/*
 343 * Add region to DMM transaction.  If pages or pages[i] is NULL, then the
 344 * corresponding slot is cleared (ie. dummy_pa is programmed)
 345 */
 346static void dmm_txn_append(struct dmm_txn *txn, struct pat_area *area,
 347		struct page **pages, u32 npages, u32 roll)
 348{
 349	dma_addr_t pat_pa = 0, data_pa = 0;
 350	u32 *data;
 351	struct pat *pat;
 352	struct refill_engine *engine = txn->engine_handle;
 353	int columns = (1 + area->x1 - area->x0);
 354	int rows = (1 + area->y1 - area->y0);
 355	int i = columns*rows;
 356
 357	pat = alloc_dma(txn, sizeof(*pat), &pat_pa);
 358
 359	if (txn->last_pat)
 360		txn->last_pat->next_pa = (u32)pat_pa;
 361
 362	pat->area = *area;
 363
 364	/* adjust Y coordinates based off of container parameters */
 365	pat->area.y0 += engine->tcm->y_offset;
 366	pat->area.y1 += engine->tcm->y_offset;
 367
 368	pat->ctrl = (struct pat_ctrl){
 369			.start = 1,
 370			.lut_id = engine->tcm->lut_id,
 371		};
 372
 373	data = alloc_dma(txn, 4*i, &data_pa);
 374	/* FIXME: what if data_pa is more than 32-bit ? */
 375	pat->data_pa = data_pa;
 376
 377	while (i--) {
 378		int n = i + roll;
 379		if (n >= npages)
 380			n -= npages;
 381		data[i] = (pages && pages[n]) ?
 382			page_to_phys(pages[n]) : engine->dmm->dummy_pa;
 383	}
 384
 385	txn->last_pat = pat;
 386
 387	return;
 388}
 389
 390/*
 391 * Commit the DMM transaction.
 392 */
 393static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
 394{
 395	int ret = 0;
 396	struct refill_engine *engine = txn->engine_handle;
 397	struct dmm *dmm = engine->dmm;
 398
 399	if (!txn->last_pat) {
 400		dev_err(engine->dmm->dev, "need at least one txn\n");
 401		ret = -EINVAL;
 402		goto cleanup;
 403	}
 404
 405	txn->last_pat->next_pa = 0;
 406	/* ensure that the written descriptors are visible to DMM */
 407	wmb();
 408
 409	/*
 410	 * NOTE: the wmb() above should be enough, but there seems to be a bug
 411	 * in OMAP's memory barrier implementation, which in some rare cases may
 412	 * cause the writes not to be observable after wmb().
 413	 */
 414
 415	/* read back to ensure the data is in RAM */
 416	readl((__iomem void *)&txn->last_pat->next_pa);
 417
 418	/* write to PAT_DESCR to clear out any pending transaction */
 419	dmm_write(dmm, 0x0, reg[PAT_DESCR][engine->id]);
 420
 421	/* wait for engine ready: */
 422	ret = wait_status(engine, DMM_PATSTATUS_READY);
 423	if (ret) {
 424		ret = -EFAULT;
 425		goto cleanup;
 426	}
 427
 428	/* mark whether it is async to denote list management in IRQ handler */
 429	engine->async = wait ? false : true;
 430	reinit_completion(&engine->compl);
 431	/* verify that the irq handler sees the 'async' and completion value */
 432	smp_mb();
 433
 434	/* kick reload */
 435	dmm_write(dmm, engine->refill_pa, reg[PAT_DESCR][engine->id]);
 436
 437	if (wait) {
 438		if (!wait_for_completion_timeout(&engine->compl,
 439				msecs_to_jiffies(100))) {
 440			dev_err(dmm->dev, "timed out waiting for done\n");
 441			ret = -ETIMEDOUT;
 442			goto cleanup;
 443		}
 444
 445		/* Check the engine status before continue */
 446		ret = wait_status(engine, DMM_PATSTATUS_READY |
 447				  DMM_PATSTATUS_VALID | DMM_PATSTATUS_DONE);
 448	}
 449
 450cleanup:
 451	/* only place engine back on list if we are done with it */
 452	if (ret || wait)
 453		release_engine(engine);
 454
 455	return ret;
 456}
 457
 458/*
 459 * DMM programming
 460 */
 461static int fill(struct tcm_area *area, struct page **pages,
 462		u32 npages, u32 roll, bool wait)
 463{
 464	int ret = 0;
 465	struct tcm_area slice, area_s;
 466	struct dmm_txn *txn;
 467
 468	/*
 469	 * FIXME
 470	 *
 471	 * Asynchronous fill does not work reliably, as the driver does not
 472	 * handle errors in the async code paths. The fill operation may
 473	 * silently fail, leading to leaking DMM engines, which may eventually
 474	 * lead to deadlock if we run out of DMM engines.
 475	 *
 476	 * For now, always set 'wait' so that we only use sync fills. Async
 477	 * fills should be fixed, or alternatively we could decide to only
 478	 * support sync fills and so the whole async code path could be removed.
 479	 */
 480
 481	wait = true;
 482
 483	txn = dmm_txn_init(omap_dmm, area->tcm);
 484	if (IS_ERR_OR_NULL(txn))
 485		return -ENOMEM;
 486
 487	tcm_for_each_slice(slice, *area, area_s) {
 488		struct pat_area p_area = {
 489				.x0 = slice.p0.x,  .y0 = slice.p0.y,
 490				.x1 = slice.p1.x,  .y1 = slice.p1.y,
 491		};
 492
 493		dmm_txn_append(txn, &p_area, pages, npages, roll);
 494
 495		roll += tcm_sizeof(slice);
 496	}
 497
 498	ret = dmm_txn_commit(txn, wait);
 499
 500	return ret;
 501}
 502
 503/*
 504 * Pin/unpin
 505 */
 506
 507/* note: slots for which pages[i] == NULL are filled w/ dummy page
 508 */
 509int tiler_pin(struct tiler_block *block, struct page **pages,
 510		u32 npages, u32 roll, bool wait)
 511{
 512	int ret;
 513
 514	ret = fill(&block->area, pages, npages, roll, wait);
 515
 516	if (ret)
 517		tiler_unpin(block);
 518
 519	return ret;
 520}
 521
 522int tiler_unpin(struct tiler_block *block)
 523{
 524	return fill(&block->area, NULL, 0, 0, false);
 525}
 526
 527/*
 528 * Reserve/release
 529 */
 530struct tiler_block *tiler_reserve_2d(enum tiler_fmt fmt, u16 w,
 531		u16 h, u16 align)
 532{
 533	struct tiler_block *block;
 534	u32 min_align = 128;
 535	int ret;
 536	unsigned long flags;
 537	u32 slot_bytes;
 538
 539	block = kzalloc(sizeof(*block), GFP_KERNEL);
 540	if (!block)
 541		return ERR_PTR(-ENOMEM);
 542
 543	BUG_ON(!validfmt(fmt));
 544
 545	/* convert width/height to slots */
 546	w = DIV_ROUND_UP(w, geom[fmt].slot_w);
 547	h = DIV_ROUND_UP(h, geom[fmt].slot_h);
 548
 549	/* convert alignment to slots */
 550	slot_bytes = geom[fmt].slot_w * geom[fmt].cpp;
 551	min_align = max(min_align, slot_bytes);
 552	align = (align > min_align) ? ALIGN(align, min_align) : min_align;
 553	align /= slot_bytes;
 554
 555	block->fmt = fmt;
 556
 557	ret = tcm_reserve_2d(containers[fmt], w, h, align, -1, slot_bytes,
 558			&block->area);
 559	if (ret) {
 560		kfree(block);
 561		return ERR_PTR(-ENOMEM);
 562	}
 563
 564	/* add to allocation list */
 565	spin_lock_irqsave(&list_lock, flags);
 566	list_add(&block->alloc_node, &omap_dmm->alloc_head);
 567	spin_unlock_irqrestore(&list_lock, flags);
 568
 569	return block;
 570}
 571
 572struct tiler_block *tiler_reserve_1d(size_t size)
 573{
 574	struct tiler_block *block = kzalloc(sizeof(*block), GFP_KERNEL);
 575	int num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
 576	unsigned long flags;
 577
 578	if (!block)
 579		return ERR_PTR(-ENOMEM);
 580
 581	block->fmt = TILFMT_PAGE;
 582
 583	if (tcm_reserve_1d(containers[TILFMT_PAGE], num_pages,
 584				&block->area)) {
 585		kfree(block);
 586		return ERR_PTR(-ENOMEM);
 587	}
 588
 589	spin_lock_irqsave(&list_lock, flags);
 590	list_add(&block->alloc_node, &omap_dmm->alloc_head);
 591	spin_unlock_irqrestore(&list_lock, flags);
 592
 593	return block;
 594}
 595
 596/* note: if you have pin'd pages, you should have already unpin'd first! */
 597int tiler_release(struct tiler_block *block)
 598{
 599	int ret = tcm_free(&block->area);
 600	unsigned long flags;
 601
 602	if (block->area.tcm)
 603		dev_err(omap_dmm->dev, "failed to release block\n");
 604
 605	spin_lock_irqsave(&list_lock, flags);
 606	list_del(&block->alloc_node);
 607	spin_unlock_irqrestore(&list_lock, flags);
 608
 609	kfree(block);
 610	return ret;
 611}
 612
 613/*
 614 * Utils
 615 */
 616
 617/* calculate the tiler space address of a pixel in a view orientation...
 618 * below description copied from the display subsystem section of TRM:
 619 *
 620 * When the TILER is addressed, the bits:
 621 *   [28:27] = 0x0 for 8-bit tiled
 622 *             0x1 for 16-bit tiled
 623 *             0x2 for 32-bit tiled
 624 *             0x3 for page mode
 625 *   [31:29] = 0x0 for 0-degree view
 626 *             0x1 for 180-degree view + mirroring
 627 *             0x2 for 0-degree view + mirroring
 628 *             0x3 for 180-degree view
 629 *             0x4 for 270-degree view + mirroring
 630 *             0x5 for 270-degree view
 631 *             0x6 for 90-degree view
 632 *             0x7 for 90-degree view + mirroring
 633 * Otherwise the bits indicated the corresponding bit address to access
 634 * the SDRAM.
 635 */
 636static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y)
 637{
 638	u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment;
 639
 640	x_bits = CONT_WIDTH_BITS - geom[fmt].x_shft;
 641	y_bits = CONT_HEIGHT_BITS - geom[fmt].y_shft;
 642	alignment = geom[fmt].x_shft + geom[fmt].y_shft;
 643
 644	/* validate coordinate */
 645	x_mask = MASK(x_bits);
 646	y_mask = MASK(y_bits);
 647
 648	if (x < 0 || x > x_mask || y < 0 || y > y_mask) {
 649		DBG("invalid coords: %u < 0 || %u > %u || %u < 0 || %u > %u",
 650				x, x, x_mask, y, y, y_mask);
 651		return 0;
 652	}
 653
 654	/* account for mirroring */
 655	if (orient & MASK_X_INVERT)
 656		x ^= x_mask;
 657	if (orient & MASK_Y_INVERT)
 658		y ^= y_mask;
 659
 660	/* get coordinate address */
 661	if (orient & MASK_XY_FLIP)
 662		tmp = ((x << y_bits) + y);
 663	else
 664		tmp = ((y << x_bits) + x);
 665
 666	return TIL_ADDR((tmp << alignment), orient, fmt);
 667}
 668
 669dma_addr_t tiler_ssptr(struct tiler_block *block)
 670{
 671	BUG_ON(!validfmt(block->fmt));
 672
 673	return TILVIEW_8BIT + tiler_get_address(block->fmt, 0,
 674			block->area.p0.x * geom[block->fmt].slot_w,
 675			block->area.p0.y * geom[block->fmt].slot_h);
 676}
 677
 678dma_addr_t tiler_tsptr(struct tiler_block *block, u32 orient,
 679		u32 x, u32 y)
 680{
 681	struct tcm_pt *p = &block->area.p0;
 682	BUG_ON(!validfmt(block->fmt));
 683
 684	return tiler_get_address(block->fmt, orient,
 685			(p->x * geom[block->fmt].slot_w) + x,
 686			(p->y * geom[block->fmt].slot_h) + y);
 687}
 688
 689void tiler_align(enum tiler_fmt fmt, u16 *w, u16 *h)
 690{
 691	BUG_ON(!validfmt(fmt));
 692	*w = round_up(*w, geom[fmt].slot_w);
 693	*h = round_up(*h, geom[fmt].slot_h);
 694}
 695
 696u32 tiler_stride(enum tiler_fmt fmt, u32 orient)
 697{
 698	BUG_ON(!validfmt(fmt));
 699
 700	if (orient & MASK_XY_FLIP)
 701		return 1 << (CONT_HEIGHT_BITS + geom[fmt].x_shft);
 702	else
 703		return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
 704}
 705
 706size_t tiler_size(enum tiler_fmt fmt, u16 w, u16 h)
 707{
 708	tiler_align(fmt, &w, &h);
 709	return geom[fmt].cpp * w * h;
 710}
 711
 712size_t tiler_vsize(enum tiler_fmt fmt, u16 w, u16 h)
 713{
 714	BUG_ON(!validfmt(fmt));
 715	return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h;
 716}
 717
 718u32 tiler_get_cpu_cache_flags(void)
 719{
 720	return omap_dmm->plat_data->cpu_cache_flags;
 721}
 722
 723bool dmm_is_available(void)
 724{
 725	return omap_dmm ? true : false;
 726}
 727
 728static void omap_dmm_remove(struct platform_device *dev)
 729{
 730	struct tiler_block *block, *_block;
 731	int i;
 732	unsigned long flags;
 733
 734	if (omap_dmm) {
 735		/* Disable all enabled interrupts */
 736		dmm_write(omap_dmm, 0x7e7e7e7e, DMM_PAT_IRQENABLE_CLR);
 737		free_irq(omap_dmm->irq, omap_dmm);
 738
 739		/* free all area regions */
 740		spin_lock_irqsave(&list_lock, flags);
 741		list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head,
 742					alloc_node) {
 743			list_del(&block->alloc_node);
 744			kfree(block);
 745		}
 746		spin_unlock_irqrestore(&list_lock, flags);
 747
 748		for (i = 0; i < omap_dmm->num_lut; i++)
 749			if (omap_dmm->tcm && omap_dmm->tcm[i])
 750				omap_dmm->tcm[i]->deinit(omap_dmm->tcm[i]);
 751		kfree(omap_dmm->tcm);
 752
 753		kfree(omap_dmm->engines);
 754		if (omap_dmm->refill_va)
 755			dma_free_wc(omap_dmm->dev,
 756				    REFILL_BUFFER_SIZE * omap_dmm->num_engines,
 757				    omap_dmm->refill_va, omap_dmm->refill_pa);
 758		if (omap_dmm->dummy_page)
 759			__free_page(omap_dmm->dummy_page);
 760
 761		if (omap_dmm->dmm_workaround)
 762			dmm_workaround_uninit(omap_dmm);
 763
 764		iounmap(omap_dmm->base);
 765		kfree(omap_dmm);
 766		omap_dmm = NULL;
 767	}
 768}
 769
 770static int omap_dmm_probe(struct platform_device *dev)
 771{
 772	int ret = -EFAULT, i;
 773	struct tcm_area area = {0};
 774	u32 hwinfo, pat_geom;
 775	struct resource *mem;
 776
 777	omap_dmm = kzalloc(sizeof(*omap_dmm), GFP_KERNEL);
 778	if (!omap_dmm)
 779		goto fail;
 780
 781	/* initialize lists */
 782	INIT_LIST_HEAD(&omap_dmm->alloc_head);
 783	INIT_LIST_HEAD(&omap_dmm->idle_head);
 784
 785	init_waitqueue_head(&omap_dmm->engine_queue);
 786
 787	if (dev->dev.of_node) {
 788		const struct of_device_id *match;
 789
 790		match = of_match_node(dmm_of_match, dev->dev.of_node);
 791		if (!match) {
 792			dev_err(&dev->dev, "failed to find matching device node\n");
 793			ret = -ENODEV;
 794			goto fail;
 795		}
 796
 797		omap_dmm->plat_data = match->data;
 798	}
 799
 800	/* lookup hwmod data - base address and irq */
 801	mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
 802	if (!mem) {
 803		dev_err(&dev->dev, "failed to get base address resource\n");
 804		goto fail;
 805	}
 806
 807	omap_dmm->phys_base = mem->start;
 808	omap_dmm->base = ioremap(mem->start, SZ_2K);
 809
 810	if (!omap_dmm->base) {
 811		dev_err(&dev->dev, "failed to get dmm base address\n");
 812		goto fail;
 813	}
 814
 815	omap_dmm->irq = platform_get_irq(dev, 0);
 816	if (omap_dmm->irq < 0)
 817		goto fail;
 818
 819	omap_dmm->dev = &dev->dev;
 820
 821	if (of_machine_is_compatible("ti,dra7")) {
 822		/*
 823		 * DRA7 Errata i878 says that MPU should not be used to access
 824		 * RAM and DMM at the same time. As it's not possible to prevent
 825		 * MPU accessing RAM, we need to access DMM via a proxy.
 826		 */
 827		if (!dmm_workaround_init(omap_dmm)) {
 828			omap_dmm->dmm_workaround = true;
 829			dev_info(&dev->dev,
 830				"workaround for errata i878 in use\n");
 831		} else {
 832			dev_warn(&dev->dev,
 833				 "failed to initialize work-around for i878\n");
 834		}
 835	}
 836
 837	hwinfo = dmm_read(omap_dmm, DMM_PAT_HWINFO);
 838	omap_dmm->num_engines = (hwinfo >> 24) & 0x1F;
 839	omap_dmm->num_lut = (hwinfo >> 16) & 0x1F;
 840	omap_dmm->container_width = 256;
 841	omap_dmm->container_height = 128;
 842
 843	atomic_set(&omap_dmm->engine_counter, omap_dmm->num_engines);
 844
 845	/* read out actual LUT width and height */
 846	pat_geom = dmm_read(omap_dmm, DMM_PAT_GEOMETRY);
 847	omap_dmm->lut_width = ((pat_geom >> 16) & 0xF) << 5;
 848	omap_dmm->lut_height = ((pat_geom >> 24) & 0xF) << 5;
 849
 850	/* increment LUT by one if on OMAP5 */
 851	/* LUT has twice the height, and is split into a separate container */
 852	if (omap_dmm->lut_height != omap_dmm->container_height)
 853		omap_dmm->num_lut++;
 854
 855	/* initialize DMM registers */
 856	dmm_write(omap_dmm, 0x88888888, DMM_PAT_VIEW__0);
 857	dmm_write(omap_dmm, 0x88888888, DMM_PAT_VIEW__1);
 858	dmm_write(omap_dmm, 0x80808080, DMM_PAT_VIEW_MAP__0);
 859	dmm_write(omap_dmm, 0x80000000, DMM_PAT_VIEW_MAP_BASE);
 860	dmm_write(omap_dmm, 0x88888888, DMM_TILER_OR__0);
 861	dmm_write(omap_dmm, 0x88888888, DMM_TILER_OR__1);
 862
 863	omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
 864	if (!omap_dmm->dummy_page) {
 865		dev_err(&dev->dev, "could not allocate dummy page\n");
 866		ret = -ENOMEM;
 867		goto fail;
 868	}
 869
 870	/* set dma mask for device */
 871	ret = dma_set_coherent_mask(&dev->dev, DMA_BIT_MASK(32));
 872	if (ret)
 873		goto fail;
 874
 875	omap_dmm->dummy_pa = page_to_phys(omap_dmm->dummy_page);
 876
 877	/* alloc refill memory */
 878	omap_dmm->refill_va = dma_alloc_wc(&dev->dev,
 879					   REFILL_BUFFER_SIZE * omap_dmm->num_engines,
 880					   &omap_dmm->refill_pa, GFP_KERNEL);
 881	if (!omap_dmm->refill_va) {
 882		dev_err(&dev->dev, "could not allocate refill memory\n");
 883		ret = -ENOMEM;
 884		goto fail;
 885	}
 886
 887	/* alloc engines */
 888	omap_dmm->engines = kcalloc(omap_dmm->num_engines,
 889				    sizeof(*omap_dmm->engines), GFP_KERNEL);
 890	if (!omap_dmm->engines) {
 891		ret = -ENOMEM;
 892		goto fail;
 893	}
 894
 895	for (i = 0; i < omap_dmm->num_engines; i++) {
 896		omap_dmm->engines[i].id = i;
 897		omap_dmm->engines[i].dmm = omap_dmm;
 898		omap_dmm->engines[i].refill_va = omap_dmm->refill_va +
 899						(REFILL_BUFFER_SIZE * i);
 900		omap_dmm->engines[i].refill_pa = omap_dmm->refill_pa +
 901						(REFILL_BUFFER_SIZE * i);
 902		init_completion(&omap_dmm->engines[i].compl);
 903
 904		list_add(&omap_dmm->engines[i].idle_node, &omap_dmm->idle_head);
 905	}
 906
 907	omap_dmm->tcm = kcalloc(omap_dmm->num_lut, sizeof(*omap_dmm->tcm),
 908				GFP_KERNEL);
 909	if (!omap_dmm->tcm) {
 910		ret = -ENOMEM;
 911		goto fail;
 912	}
 913
 914	/* init containers */
 915	/* Each LUT is associated with a TCM (container manager).  We use the
 916	   lut_id to denote the lut_id used to identify the correct LUT for
 917	   programming during reill operations */
 918	for (i = 0; i < omap_dmm->num_lut; i++) {
 919		omap_dmm->tcm[i] = sita_init(omap_dmm->container_width,
 920						omap_dmm->container_height);
 921
 922		if (!omap_dmm->tcm[i]) {
 923			dev_err(&dev->dev, "failed to allocate container\n");
 924			ret = -ENOMEM;
 925			goto fail;
 926		}
 927
 928		omap_dmm->tcm[i]->lut_id = i;
 929	}
 930
 931	/* assign access mode containers to applicable tcm container */
 932	/* OMAP 4 has 1 container for all 4 views */
 933	/* OMAP 5 has 2 containers, 1 for 2D and 1 for 1D */
 934	containers[TILFMT_8BIT] = omap_dmm->tcm[0];
 935	containers[TILFMT_16BIT] = omap_dmm->tcm[0];
 936	containers[TILFMT_32BIT] = omap_dmm->tcm[0];
 937
 938	if (omap_dmm->container_height != omap_dmm->lut_height) {
 939		/* second LUT is used for PAGE mode.  Programming must use
 940		   y offset that is added to all y coordinates.  LUT id is still
 941		   0, because it is the same LUT, just the upper 128 lines */
 942		containers[TILFMT_PAGE] = omap_dmm->tcm[1];
 943		omap_dmm->tcm[1]->y_offset = OMAP5_LUT_OFFSET;
 944		omap_dmm->tcm[1]->lut_id = 0;
 945	} else {
 946		containers[TILFMT_PAGE] = omap_dmm->tcm[0];
 947	}
 948
 949	area = (struct tcm_area) {
 950		.tcm = NULL,
 951		.p1.x = omap_dmm->container_width - 1,
 952		.p1.y = omap_dmm->container_height - 1,
 953	};
 954
 955	ret = request_irq(omap_dmm->irq, omap_dmm_irq_handler, IRQF_SHARED,
 956				"omap_dmm_irq_handler", omap_dmm);
 957
 958	if (ret) {
 959		dev_err(&dev->dev, "couldn't register IRQ %d, error %d\n",
 960			omap_dmm->irq, ret);
 961		omap_dmm->irq = -1;
 962		goto fail;
 963	}
 964
 965	/* Enable all interrupts for each refill engine except
 966	 * ERR_LUT_MISS<n> (which is just advisory, and we don't care
 967	 * about because we want to be able to refill live scanout
 968	 * buffers for accelerated pan/scroll) and FILL_DSC<n> which
 969	 * we just generally don't care about.
 970	 */
 971	dmm_write(omap_dmm, 0x7e7e7e7e, DMM_PAT_IRQENABLE_SET);
 972
 973	/* initialize all LUTs to dummy page entries */
 974	for (i = 0; i < omap_dmm->num_lut; i++) {
 975		area.tcm = omap_dmm->tcm[i];
 976		if (fill(&area, NULL, 0, 0, true))
 977			dev_err(omap_dmm->dev, "refill failed");
 978	}
 979
 980	dev_info(omap_dmm->dev, "initialized all PAT entries\n");
 981
 982	return 0;
 983
 984fail:
 985	omap_dmm_remove(dev);
 986	return ret;
 987}
 988
 989/*
 990 * debugfs support
 991 */
 992
 993#ifdef CONFIG_DEBUG_FS
 994
 995static const char *alphabet = "abcdefghijklmnopqrstuvwxyz"
 996				"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
 997static const char *special = ".,:;'\"`~!^-+";
 998
 999static void fill_map(char **map, int xdiv, int ydiv, struct tcm_area *a,
1000							char c, bool ovw)
1001{
1002	int x, y;
1003	for (y = a->p0.y / ydiv; y <= a->p1.y / ydiv; y++)
1004		for (x = a->p0.x / xdiv; x <= a->p1.x / xdiv; x++)
1005			if (map[y][x] == ' ' || ovw)
1006				map[y][x] = c;
1007}
1008
1009static void fill_map_pt(char **map, int xdiv, int ydiv, struct tcm_pt *p,
1010									char c)
1011{
1012	map[p->y / ydiv][p->x / xdiv] = c;
1013}
1014
1015static char read_map_pt(char **map, int xdiv, int ydiv, struct tcm_pt *p)
1016{
1017	return map[p->y / ydiv][p->x / xdiv];
1018}
1019
1020static int map_width(int xdiv, int x0, int x1)
1021{
1022	return (x1 / xdiv) - (x0 / xdiv) + 1;
1023}
1024
1025static void text_map(char **map, int xdiv, char *nice, int yd, int x0, int x1)
1026{
1027	char *p = map[yd] + (x0 / xdiv);
1028	int w = (map_width(xdiv, x0, x1) - strlen(nice)) / 2;
1029	if (w >= 0) {
1030		p += w;
1031		while (*nice)
1032			*p++ = *nice++;
1033	}
1034}
1035
1036static void map_1d_info(char **map, int xdiv, int ydiv, char *nice,
1037							struct tcm_area *a)
1038{
1039	sprintf(nice, "%dK", tcm_sizeof(*a) * 4);
1040	if (a->p0.y + 1 < a->p1.y) {
1041		text_map(map, xdiv, nice, (a->p0.y + a->p1.y) / 2 / ydiv, 0,
1042							256 - 1);
1043	} else if (a->p0.y < a->p1.y) {
1044		if (strlen(nice) < map_width(xdiv, a->p0.x, 256 - 1))
1045			text_map(map, xdiv, nice, a->p0.y / ydiv,
1046					a->p0.x + xdiv,	256 - 1);
1047		else if (strlen(nice) < map_width(xdiv, 0, a->p1.x))
1048			text_map(map, xdiv, nice, a->p1.y / ydiv,
1049					0, a->p1.y - xdiv);
1050	} else if (strlen(nice) + 1 < map_width(xdiv, a->p0.x, a->p1.x)) {
1051		text_map(map, xdiv, nice, a->p0.y / ydiv, a->p0.x, a->p1.x);
1052	}
1053}
1054
1055static void map_2d_info(char **map, int xdiv, int ydiv, char *nice,
1056							struct tcm_area *a)
1057{
1058	sprintf(nice, "(%d*%d)", tcm_awidth(*a), tcm_aheight(*a));
1059	if (strlen(nice) + 1 < map_width(xdiv, a->p0.x, a->p1.x))
1060		text_map(map, xdiv, nice, (a->p0.y + a->p1.y) / 2 / ydiv,
1061							a->p0.x, a->p1.x);
1062}
1063
1064int tiler_map_show(struct seq_file *s, void *arg)
1065{
1066	int xdiv = 2, ydiv = 1;
1067	char **map = NULL, *global_map;
1068	struct tiler_block *block;
1069	struct tcm_area a, p;
1070	int i;
1071	const char *m2d = alphabet;
1072	const char *a2d = special;
1073	const char *m2dp = m2d, *a2dp = a2d;
1074	char nice[128];
1075	int h_adj;
1076	int w_adj;
1077	unsigned long flags;
1078	int lut_idx;
1079
1080
1081	if (!omap_dmm) {
1082		/* early return if dmm/tiler device is not initialized */
1083		return 0;
1084	}
1085
1086	h_adj = omap_dmm->container_height / ydiv;
1087	w_adj = omap_dmm->container_width / xdiv;
1088
1089	map = kmalloc_array(h_adj, sizeof(*map), GFP_KERNEL);
1090	global_map = kmalloc_array(w_adj + 1, h_adj, GFP_KERNEL);
1091
1092	if (!map || !global_map)
1093		goto error;
1094
1095	for (lut_idx = 0; lut_idx < omap_dmm->num_lut; lut_idx++) {
1096		memset(map, 0, h_adj * sizeof(*map));
1097		memset(global_map, ' ', (w_adj + 1) * h_adj);
1098
1099		for (i = 0; i < omap_dmm->container_height; i++) {
1100			map[i] = global_map + i * (w_adj + 1);
1101			map[i][w_adj] = 0;
1102		}
1103
1104		spin_lock_irqsave(&list_lock, flags);
1105
1106		list_for_each_entry(block, &omap_dmm->alloc_head, alloc_node) {
1107			if (block->area.tcm == omap_dmm->tcm[lut_idx]) {
1108				if (block->fmt != TILFMT_PAGE) {
1109					fill_map(map, xdiv, ydiv, &block->area,
1110						*m2dp, true);
1111					if (!*++a2dp)
1112						a2dp = a2d;
1113					if (!*++m2dp)
1114						m2dp = m2d;
1115					map_2d_info(map, xdiv, ydiv, nice,
1116							&block->area);
1117				} else {
1118					bool start = read_map_pt(map, xdiv,
1119						ydiv, &block->area.p0) == ' ';
1120					bool end = read_map_pt(map, xdiv, ydiv,
1121							&block->area.p1) == ' ';
1122
1123					tcm_for_each_slice(a, block->area, p)
1124						fill_map(map, xdiv, ydiv, &a,
1125							'=', true);
1126					fill_map_pt(map, xdiv, ydiv,
1127							&block->area.p0,
1128							start ? '<' : 'X');
1129					fill_map_pt(map, xdiv, ydiv,
1130							&block->area.p1,
1131							end ? '>' : 'X');
1132					map_1d_info(map, xdiv, ydiv, nice,
1133							&block->area);
1134				}
1135			}
1136		}
1137
1138		spin_unlock_irqrestore(&list_lock, flags);
1139
1140		if (s) {
1141			seq_printf(s, "CONTAINER %d DUMP BEGIN\n", lut_idx);
1142			for (i = 0; i < 128; i++)
1143				seq_printf(s, "%03d:%s\n", i, map[i]);
1144			seq_printf(s, "CONTAINER %d DUMP END\n", lut_idx);
1145		} else {
1146			dev_dbg(omap_dmm->dev, "CONTAINER %d DUMP BEGIN\n",
1147				lut_idx);
1148			for (i = 0; i < 128; i++)
1149				dev_dbg(omap_dmm->dev, "%03d:%s\n", i, map[i]);
1150			dev_dbg(omap_dmm->dev, "CONTAINER %d DUMP END\n",
1151				lut_idx);
1152		}
1153	}
1154
1155error:
1156	kfree(map);
1157	kfree(global_map);
1158
1159	return 0;
1160}
1161#endif
1162
1163#ifdef CONFIG_PM_SLEEP
1164static int omap_dmm_resume(struct device *dev)
1165{
1166	struct tcm_area area;
1167	int i;
1168
1169	if (!omap_dmm)
1170		return -ENODEV;
1171
1172	area = (struct tcm_area) {
1173		.tcm = NULL,
1174		.p1.x = omap_dmm->container_width - 1,
1175		.p1.y = omap_dmm->container_height - 1,
1176	};
1177
1178	/* initialize all LUTs to dummy page entries */
1179	for (i = 0; i < omap_dmm->num_lut; i++) {
1180		area.tcm = omap_dmm->tcm[i];
1181		if (fill(&area, NULL, 0, 0, true))
1182			dev_err(dev, "refill failed");
1183	}
1184
1185	return 0;
1186}
1187#endif
1188
1189static SIMPLE_DEV_PM_OPS(omap_dmm_pm_ops, NULL, omap_dmm_resume);
1190
1191#if defined(CONFIG_OF)
1192static const struct dmm_platform_data dmm_omap4_platform_data = {
1193	.cpu_cache_flags = OMAP_BO_WC,
1194};
1195
1196static const struct dmm_platform_data dmm_omap5_platform_data = {
1197	.cpu_cache_flags = OMAP_BO_UNCACHED,
1198};
1199
1200static const struct of_device_id dmm_of_match[] = {
1201	{
1202		.compatible = "ti,omap4-dmm",
1203		.data = &dmm_omap4_platform_data,
1204	},
1205	{
1206		.compatible = "ti,omap5-dmm",
1207		.data = &dmm_omap5_platform_data,
1208	},
1209	{},
1210};
1211#endif
1212
1213struct platform_driver omap_dmm_driver = {
1214	.probe = omap_dmm_probe,
1215	.remove = omap_dmm_remove,
1216	.driver = {
1217		.name = DMM_DRIVER_NAME,
1218		.of_match_table = of_match_ptr(dmm_of_match),
1219		.pm = &omap_dmm_pm_ops,
1220	},
1221};
1222
1223MODULE_LICENSE("GPL v2");
1224MODULE_AUTHOR("Andy Gross <andy.gross@ti.com>");
1225MODULE_DESCRIPTION("OMAP DMM/Tiler Driver");
~/ Read-only file preview.