11.2Sriastrad/*	$NetBSD: r128_cce.c,v 1.3 2021/12/18 23:45:42 riastradh Exp $	*/
21.2Sriastrad
31.1Sriastrad/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*-
41.1Sriastrad * Created: Wed Apr  5 19:24:19 2000 by kevin@precisioninsight.com
51.1Sriastrad */
61.1Sriastrad/*
71.1Sriastrad * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas.
81.1Sriastrad * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
91.1Sriastrad * All Rights Reserved.
101.1Sriastrad *
111.1Sriastrad * Permission is hereby granted, free of charge, to any person obtaining a
121.1Sriastrad * copy of this software and associated documentation files (the "Software"),
131.1Sriastrad * to deal in the Software without restriction, including without limitation
141.1Sriastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense,
151.1Sriastrad * and/or sell copies of the Software, and to permit persons to whom the
161.1Sriastrad * Software is furnished to do so, subject to the following conditions:
171.1Sriastrad *
181.1Sriastrad * The above copyright notice and this permission notice (including the next
191.1Sriastrad * paragraph) shall be included in all copies or substantial portions of the
201.1Sriastrad * Software.
211.1Sriastrad *
221.1Sriastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
231.1Sriastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
241.1Sriastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
251.1Sriastrad * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
261.1Sriastrad * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
271.1Sriastrad * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
281.1Sriastrad * DEALINGS IN THE SOFTWARE.
291.1Sriastrad *
301.1Sriastrad * Authors:
311.1Sriastrad *    Gareth Hughes <gareth@valinux.com>
321.1Sriastrad */
331.1Sriastrad
341.2Sriastrad#include <sys/cdefs.h>
351.2Sriastrad__KERNEL_RCSID(0, "$NetBSD: r128_cce.c,v 1.3 2021/12/18 23:45:42 riastradh Exp $");
361.2Sriastrad
371.3Sriastrad#include <linux/delay.h>
381.3Sriastrad#include <linux/dma-mapping.h>
391.1Sriastrad#include <linux/firmware.h>
401.3Sriastrad#include <linux/module.h>
411.1Sriastrad#include <linux/platform_device.h>
421.1Sriastrad#include <linux/slab.h>
431.3Sriastrad#include <linux/uaccess.h>
441.1Sriastrad
451.3Sriastrad#include <drm/drm_agpsupport.h>
461.3Sriastrad#include <drm/drm_device.h>
471.3Sriastrad#include <drm/drm_file.h>
481.3Sriastrad#include <drm/drm_irq.h>
491.3Sriastrad#include <drm/drm_print.h>
501.1Sriastrad#include <drm/r128_drm.h>
511.3Sriastrad
521.1Sriastrad#include "r128_drv.h"
531.1Sriastrad
541.1Sriastrad#define R128_FIFO_DEBUG		0
551.1Sriastrad
561.1Sriastrad#define FIRMWARE_NAME		"r128/r128_cce.bin"
571.1Sriastrad
581.1SriastradMODULE_FIRMWARE(FIRMWARE_NAME);
591.1Sriastrad
601.1Sriastradstatic int R128_READ_PLL(struct drm_device *dev, int addr)
611.1Sriastrad{
621.1Sriastrad	drm_r128_private_t *dev_priv = dev->dev_private;
631.1Sriastrad
641.1Sriastrad	R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f);
651.1Sriastrad	return R128_READ(R128_CLOCK_CNTL_DATA);
661.1Sriastrad}
671.1Sriastrad
681.1Sriastrad#if R128_FIFO_DEBUG
691.1Sriastradstatic void r128_status(drm_r128_private_t *dev_priv)
701.1Sriastrad{
711.1Sriastrad	printk("GUI_STAT           = 0x%08x\n",
721.1Sriastrad	       (unsigned int)R128_READ(R128_GUI_STAT));
731.1Sriastrad	printk("PM4_STAT           = 0x%08x\n",
741.1Sriastrad	       (unsigned int)R128_READ(R128_PM4_STAT));
751.1Sriastrad	printk("PM4_BUFFER_DL_WPTR = 0x%08x\n",
761.1Sriastrad	       (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR));
771.1Sriastrad	printk("PM4_BUFFER_DL_RPTR = 0x%08x\n",
781.1Sriastrad	       (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR));
791.1Sriastrad	printk("PM4_MICRO_CNTL     = 0x%08x\n",
801.1Sriastrad	       (unsigned int)R128_READ(R128_PM4_MICRO_CNTL));
811.1Sriastrad	printk("PM4_BUFFER_CNTL    = 0x%08x\n",
821.1Sriastrad	       (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL));
831.1Sriastrad}
841.1Sriastrad#endif
851.1Sriastrad
861.1Sriastrad/* ================================================================
871.1Sriastrad * Engine, FIFO control
881.1Sriastrad */
891.1Sriastrad
901.1Sriastradstatic int r128_do_pixcache_flush(drm_r128_private_t *dev_priv)
911.1Sriastrad{
921.1Sriastrad	u32 tmp;
931.1Sriastrad	int i;
941.1Sriastrad
951.1Sriastrad	tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL;
961.1Sriastrad	R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp);
971.1Sriastrad
981.1Sriastrad	for (i = 0; i < dev_priv->usec_timeout; i++) {
991.1Sriastrad		if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY))
1001.1Sriastrad			return 0;
1011.3Sriastrad		udelay(1);
1021.1Sriastrad	}
1031.1Sriastrad
1041.1Sriastrad#if R128_FIFO_DEBUG
1051.1Sriastrad	DRM_ERROR("failed!\n");
1061.1Sriastrad#endif
1071.1Sriastrad	return -EBUSY;
1081.1Sriastrad}
1091.1Sriastrad
1101.1Sriastradstatic int r128_do_wait_for_fifo(drm_r128_private_t *dev_priv, int entries)
1111.1Sriastrad{
1121.1Sriastrad	int i;
1131.1Sriastrad
1141.1Sriastrad	for (i = 0; i < dev_priv->usec_timeout; i++) {
1151.1Sriastrad		int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK;
1161.1Sriastrad		if (slots >= entries)
1171.1Sriastrad			return 0;
1181.3Sriastrad		udelay(1);
1191.1Sriastrad	}
1201.1Sriastrad
1211.1Sriastrad#if R128_FIFO_DEBUG
1221.1Sriastrad	DRM_ERROR("failed!\n");
1231.1Sriastrad#endif
1241.1Sriastrad	return -EBUSY;
1251.1Sriastrad}
1261.1Sriastrad
1271.1Sriastradstatic int r128_do_wait_for_idle(drm_r128_private_t *dev_priv)
1281.1Sriastrad{
1291.1Sriastrad	int i, ret;
1301.1Sriastrad
1311.1Sriastrad	ret = r128_do_wait_for_fifo(dev_priv, 64);
1321.1Sriastrad	if (ret)
1331.1Sriastrad		return ret;
1341.1Sriastrad
1351.1Sriastrad	for (i = 0; i < dev_priv->usec_timeout; i++) {
1361.1Sriastrad		if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) {
1371.1Sriastrad			r128_do_pixcache_flush(dev_priv);
1381.1Sriastrad			return 0;
1391.1Sriastrad		}
1401.3Sriastrad		udelay(1);
1411.1Sriastrad	}
1421.1Sriastrad
1431.1Sriastrad#if R128_FIFO_DEBUG
1441.1Sriastrad	DRM_ERROR("failed!\n");
1451.1Sriastrad#endif
1461.1Sriastrad	return -EBUSY;
1471.1Sriastrad}
1481.1Sriastrad
1491.1Sriastrad/* ================================================================
1501.1Sriastrad * CCE control, initialization
1511.1Sriastrad */
1521.1Sriastrad
1531.1Sriastrad/* Load the microcode for the CCE */
1541.1Sriastradstatic int r128_cce_load_microcode(drm_r128_private_t *dev_priv)
1551.1Sriastrad{
1561.1Sriastrad	struct platform_device *pdev;
1571.1Sriastrad	const struct firmware *fw;
1581.1Sriastrad	const __be32 *fw_data;
1591.1Sriastrad	int rc, i;
1601.1Sriastrad
1611.1Sriastrad	DRM_DEBUG("\n");
1621.1Sriastrad
1631.1Sriastrad	pdev = platform_device_register_simple("r128_cce", 0, NULL, 0);
1641.1Sriastrad	if (IS_ERR(pdev)) {
1651.3Sriastrad		pr_err("r128_cce: Failed to register firmware\n");
1661.1Sriastrad		return PTR_ERR(pdev);
1671.1Sriastrad	}
1681.1Sriastrad	rc = request_firmware(&fw, FIRMWARE_NAME, &pdev->dev);
1691.1Sriastrad	platform_device_unregister(pdev);
1701.1Sriastrad	if (rc) {
1711.3Sriastrad		pr_err("r128_cce: Failed to load firmware \"%s\"\n",
1721.1Sriastrad		       FIRMWARE_NAME);
1731.1Sriastrad		return rc;
1741.1Sriastrad	}
1751.1Sriastrad
1761.1Sriastrad	if (fw->size != 256 * 8) {
1771.3Sriastrad		pr_err("r128_cce: Bogus length %zu in firmware \"%s\"\n",
1781.1Sriastrad		       fw->size, FIRMWARE_NAME);
1791.1Sriastrad		rc = -EINVAL;
1801.1Sriastrad		goto out_release;
1811.1Sriastrad	}
1821.1Sriastrad
1831.1Sriastrad	r128_do_wait_for_idle(dev_priv);
1841.1Sriastrad
1851.1Sriastrad	fw_data = (const __be32 *)fw->data;
1861.1Sriastrad	R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
1871.1Sriastrad	for (i = 0; i < 256; i++) {
1881.1Sriastrad		R128_WRITE(R128_PM4_MICROCODE_DATAH,
1891.1Sriastrad			   be32_to_cpup(&fw_data[i * 2]));
1901.1Sriastrad		R128_WRITE(R128_PM4_MICROCODE_DATAL,
1911.1Sriastrad			   be32_to_cpup(&fw_data[i * 2 + 1]));
1921.1Sriastrad	}
1931.1Sriastrad
1941.1Sriastradout_release:
1951.1Sriastrad	release_firmware(fw);
1961.1Sriastrad	return rc;
1971.1Sriastrad}
1981.1Sriastrad
1991.1Sriastrad/* Flush any pending commands to the CCE.  This should only be used just
2001.1Sriastrad * prior to a wait for idle, as it informs the engine that the command
2011.1Sriastrad * stream is ending.
2021.1Sriastrad */
2031.1Sriastradstatic void r128_do_cce_flush(drm_r128_private_t *dev_priv)
2041.1Sriastrad{
2051.1Sriastrad	u32 tmp;
2061.1Sriastrad
2071.1Sriastrad	tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE;
2081.1Sriastrad	R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp);
2091.1Sriastrad}
2101.1Sriastrad
2111.1Sriastrad/* Wait for the CCE to go idle.
2121.1Sriastrad */
2131.1Sriastradint r128_do_cce_idle(drm_r128_private_t *dev_priv)
2141.1Sriastrad{
2151.1Sriastrad	int i;
2161.1Sriastrad
2171.1Sriastrad	for (i = 0; i < dev_priv->usec_timeout; i++) {
2181.1Sriastrad		if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) {
2191.1Sriastrad			int pm4stat = R128_READ(R128_PM4_STAT);
2201.1Sriastrad			if (((pm4stat & R128_PM4_FIFOCNT_MASK) >=
2211.1Sriastrad			     dev_priv->cce_fifo_size) &&
2221.1Sriastrad			    !(pm4stat & (R128_PM4_BUSY |
2231.1Sriastrad					 R128_PM4_GUI_ACTIVE))) {
2241.1Sriastrad				return r128_do_pixcache_flush(dev_priv);
2251.1Sriastrad			}
2261.1Sriastrad		}
2271.3Sriastrad		udelay(1);
2281.1Sriastrad	}
2291.1Sriastrad
2301.1Sriastrad#if R128_FIFO_DEBUG
2311.1Sriastrad	DRM_ERROR("failed!\n");
2321.1Sriastrad	r128_status(dev_priv);
2331.1Sriastrad#endif
2341.1Sriastrad	return -EBUSY;
2351.1Sriastrad}
2361.1Sriastrad
2371.1Sriastrad/* Start the Concurrent Command Engine.
2381.1Sriastrad */
2391.1Sriastradstatic void r128_do_cce_start(drm_r128_private_t *dev_priv)
2401.1Sriastrad{
2411.1Sriastrad	r128_do_wait_for_idle(dev_priv);
2421.1Sriastrad
2431.1Sriastrad	R128_WRITE(R128_PM4_BUFFER_CNTL,
2441.1Sriastrad		   dev_priv->cce_mode | dev_priv->ring.size_l2qw
2451.1Sriastrad		   | R128_PM4_BUFFER_CNTL_NOUPDATE);
2461.1Sriastrad	R128_READ(R128_PM4_BUFFER_ADDR);	/* as per the sample code */
2471.1Sriastrad	R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN);
2481.1Sriastrad
2491.1Sriastrad	dev_priv->cce_running = 1;
2501.1Sriastrad}
2511.1Sriastrad
2521.1Sriastrad/* Reset the Concurrent Command Engine.  This will not flush any pending
2531.1Sriastrad * commands, so you must wait for the CCE command stream to complete
2541.1Sriastrad * before calling this routine.
2551.1Sriastrad */
2561.1Sriastradstatic void r128_do_cce_reset(drm_r128_private_t *dev_priv)
2571.1Sriastrad{
2581.1Sriastrad	R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
2591.1Sriastrad	R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
2601.1Sriastrad	dev_priv->ring.tail = 0;
2611.1Sriastrad}
2621.1Sriastrad
2631.1Sriastrad/* Stop the Concurrent Command Engine.  This will not flush any pending
2641.1Sriastrad * commands, so you must flush the command stream and wait for the CCE
2651.1Sriastrad * to go idle before calling this routine.
2661.1Sriastrad */
2671.1Sriastradstatic void r128_do_cce_stop(drm_r128_private_t *dev_priv)
2681.1Sriastrad{
2691.1Sriastrad	R128_WRITE(R128_PM4_MICRO_CNTL, 0);
2701.1Sriastrad	R128_WRITE(R128_PM4_BUFFER_CNTL,
2711.1Sriastrad		   R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE);
2721.1Sriastrad
2731.1Sriastrad	dev_priv->cce_running = 0;
2741.1Sriastrad}
2751.1Sriastrad
2761.1Sriastrad/* Reset the engine.  This will stop the CCE if it is running.
2771.1Sriastrad */
2781.1Sriastradstatic int r128_do_engine_reset(struct drm_device *dev)
2791.1Sriastrad{
2801.1Sriastrad	drm_r128_private_t *dev_priv = dev->dev_private;
2811.1Sriastrad	u32 clock_cntl_index, mclk_cntl, gen_reset_cntl;
2821.1Sriastrad
2831.1Sriastrad	r128_do_pixcache_flush(dev_priv);
2841.1Sriastrad
2851.1Sriastrad	clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX);
2861.1Sriastrad	mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL);
2871.1Sriastrad
2881.1Sriastrad	R128_WRITE_PLL(R128_MCLK_CNTL,
2891.1Sriastrad		       mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP);
2901.1Sriastrad
2911.1Sriastrad	gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL);
2921.1Sriastrad
2931.1Sriastrad	/* Taken from the sample code - do not change */
2941.1Sriastrad	R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI);
2951.1Sriastrad	R128_READ(R128_GEN_RESET_CNTL);
2961.1Sriastrad	R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI);
2971.1Sriastrad	R128_READ(R128_GEN_RESET_CNTL);
2981.1Sriastrad
2991.1Sriastrad	R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl);
3001.1Sriastrad	R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index);
3011.1Sriastrad	R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl);
3021.1Sriastrad
3031.1Sriastrad	/* Reset the CCE ring */
3041.1Sriastrad	r128_do_cce_reset(dev_priv);
3051.1Sriastrad
3061.1Sriastrad	/* The CCE is no longer running after an engine reset */
3071.1Sriastrad	dev_priv->cce_running = 0;
3081.1Sriastrad
3091.1Sriastrad	/* Reset any pending vertex, indirect buffers */
3101.1Sriastrad	r128_freelist_reset(dev);
3111.1Sriastrad
3121.1Sriastrad	return 0;
3131.1Sriastrad}
3141.1Sriastrad
3151.1Sriastradstatic void r128_cce_init_ring_buffer(struct drm_device *dev,
3161.1Sriastrad				      drm_r128_private_t *dev_priv)
3171.1Sriastrad{
3181.1Sriastrad	u32 ring_start;
3191.1Sriastrad	u32 tmp;
3201.1Sriastrad
3211.1Sriastrad	DRM_DEBUG("\n");
3221.1Sriastrad
3231.1Sriastrad	/* The manual (p. 2) says this address is in "VM space".  This
3241.1Sriastrad	 * means it's an offset from the start of AGP space.
3251.1Sriastrad	 */
3261.2Sriastrad#if IS_ENABLED(CONFIG_AGP)
3271.1Sriastrad	if (!dev_priv->is_pci)
3281.1Sriastrad		ring_start = dev_priv->cce_ring->offset - dev->agp->base;
3291.1Sriastrad	else
3301.1Sriastrad#endif
3311.1Sriastrad		ring_start = dev_priv->cce_ring->offset -
3321.1Sriastrad		    (unsigned long)dev->sg->virtual;
3331.1Sriastrad
3341.1Sriastrad	R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET);
3351.1Sriastrad
3361.1Sriastrad	R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0);
3371.1Sriastrad	R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0);
3381.1Sriastrad
3391.1Sriastrad	/* Set watermark control */
3401.1Sriastrad	R128_WRITE(R128_PM4_BUFFER_WM_CNTL,
3411.1Sriastrad		   ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT)
3421.1Sriastrad		   | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT)
3431.1Sriastrad		   | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT)
3441.1Sriastrad		   | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT));
3451.1Sriastrad
3461.1Sriastrad	/* Force read.  Why?  Because it's in the examples... */
3471.1Sriastrad	R128_READ(R128_PM4_BUFFER_ADDR);
3481.1Sriastrad
3491.1Sriastrad	/* Turn on bus mastering */
3501.1Sriastrad	tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS;
3511.1Sriastrad	R128_WRITE(R128_BUS_CNTL, tmp);
3521.1Sriastrad}
3531.1Sriastrad
3541.1Sriastradstatic int r128_do_init_cce(struct drm_device *dev, drm_r128_init_t *init)
3551.1Sriastrad{
3561.1Sriastrad	drm_r128_private_t *dev_priv;
3571.1Sriastrad	int rc;
3581.1Sriastrad
3591.1Sriastrad	DRM_DEBUG("\n");
3601.1Sriastrad
3611.1Sriastrad	if (dev->dev_private) {
3621.1Sriastrad		DRM_DEBUG("called when already initialized\n");
3631.1Sriastrad		return -EINVAL;
3641.1Sriastrad	}
3651.1Sriastrad
3661.1Sriastrad	dev_priv = kzalloc(sizeof(drm_r128_private_t), GFP_KERNEL);
3671.1Sriastrad	if (dev_priv == NULL)
3681.1Sriastrad		return -ENOMEM;
3691.1Sriastrad
3701.1Sriastrad	dev_priv->is_pci = init->is_pci;
3711.1Sriastrad
3721.1Sriastrad	if (dev_priv->is_pci && !dev->sg) {
3731.1Sriastrad		DRM_ERROR("PCI GART memory not allocated!\n");
3741.1Sriastrad		dev->dev_private = (void *)dev_priv;
3751.1Sriastrad		r128_do_cleanup_cce(dev);
3761.1Sriastrad		return -EINVAL;
3771.1Sriastrad	}
3781.1Sriastrad
3791.1Sriastrad	dev_priv->usec_timeout = init->usec_timeout;
3801.1Sriastrad	if (dev_priv->usec_timeout < 1 ||
3811.1Sriastrad	    dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) {
3821.1Sriastrad		DRM_DEBUG("TIMEOUT problem!\n");
3831.1Sriastrad		dev->dev_private = (void *)dev_priv;
3841.1Sriastrad		r128_do_cleanup_cce(dev);
3851.1Sriastrad		return -EINVAL;
3861.1Sriastrad	}
3871.1Sriastrad
3881.1Sriastrad	dev_priv->cce_mode = init->cce_mode;
3891.1Sriastrad
3901.1Sriastrad	/* GH: Simple idle check.
3911.1Sriastrad	 */
3921.1Sriastrad	atomic_set(&dev_priv->idle_count, 0);
3931.1Sriastrad
3941.1Sriastrad	/* We don't support anything other than bus-mastering ring mode,
3951.1Sriastrad	 * but the ring can be in either AGP or PCI space for the ring
3961.1Sriastrad	 * read pointer.
3971.1Sriastrad	 */
3981.1Sriastrad	if ((init->cce_mode != R128_PM4_192BM) &&
3991.1Sriastrad	    (init->cce_mode != R128_PM4_128BM_64INDBM) &&
4001.1Sriastrad	    (init->cce_mode != R128_PM4_64BM_128INDBM) &&
4011.1Sriastrad	    (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) {
4021.1Sriastrad		DRM_DEBUG("Bad cce_mode!\n");
4031.1Sriastrad		dev->dev_private = (void *)dev_priv;
4041.1Sriastrad		r128_do_cleanup_cce(dev);
4051.1Sriastrad		return -EINVAL;
4061.1Sriastrad	}
4071.1Sriastrad
4081.1Sriastrad	switch (init->cce_mode) {
4091.1Sriastrad	case R128_PM4_NONPM4:
4101.1Sriastrad		dev_priv->cce_fifo_size = 0;
4111.1Sriastrad		break;
4121.1Sriastrad	case R128_PM4_192PIO:
4131.1Sriastrad	case R128_PM4_192BM:
4141.1Sriastrad		dev_priv->cce_fifo_size = 192;
4151.1Sriastrad		break;
4161.1Sriastrad	case R128_PM4_128PIO_64INDBM:
4171.1Sriastrad	case R128_PM4_128BM_64INDBM:
4181.1Sriastrad		dev_priv->cce_fifo_size = 128;
4191.1Sriastrad		break;
4201.1Sriastrad	case R128_PM4_64PIO_128INDBM:
4211.1Sriastrad	case R128_PM4_64BM_128INDBM:
4221.1Sriastrad	case R128_PM4_64PIO_64VCBM_64INDBM:
4231.1Sriastrad	case R128_PM4_64BM_64VCBM_64INDBM:
4241.1Sriastrad	case R128_PM4_64PIO_64VCPIO_64INDPIO:
4251.1Sriastrad		dev_priv->cce_fifo_size = 64;
4261.1Sriastrad		break;
4271.1Sriastrad	}
4281.1Sriastrad
4291.1Sriastrad	switch (init->fb_bpp) {
4301.1Sriastrad	case 16:
4311.1Sriastrad		dev_priv->color_fmt = R128_DATATYPE_RGB565;
4321.1Sriastrad		break;
4331.1Sriastrad	case 32:
4341.1Sriastrad	default:
4351.1Sriastrad		dev_priv->color_fmt = R128_DATATYPE_ARGB8888;
4361.1Sriastrad		break;
4371.1Sriastrad	}
4381.1Sriastrad	dev_priv->front_offset = init->front_offset;
4391.1Sriastrad	dev_priv->front_pitch = init->front_pitch;
4401.1Sriastrad	dev_priv->back_offset = init->back_offset;
4411.1Sriastrad	dev_priv->back_pitch = init->back_pitch;
4421.1Sriastrad
4431.1Sriastrad	switch (init->depth_bpp) {
4441.1Sriastrad	case 16:
4451.1Sriastrad		dev_priv->depth_fmt = R128_DATATYPE_RGB565;
4461.1Sriastrad		break;
4471.1Sriastrad	case 24:
4481.1Sriastrad	case 32:
4491.1Sriastrad	default:
4501.1Sriastrad		dev_priv->depth_fmt = R128_DATATYPE_ARGB8888;
4511.1Sriastrad		break;
4521.1Sriastrad	}
4531.1Sriastrad	dev_priv->depth_offset = init->depth_offset;
4541.1Sriastrad	dev_priv->depth_pitch = init->depth_pitch;
4551.1Sriastrad	dev_priv->span_offset = init->span_offset;
4561.1Sriastrad
4571.1Sriastrad	dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) |
4581.1Sriastrad					  (dev_priv->front_offset >> 5));
4591.1Sriastrad	dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) |
4601.1Sriastrad					 (dev_priv->back_offset >> 5));
4611.1Sriastrad	dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
4621.1Sriastrad					  (dev_priv->depth_offset >> 5) |
4631.1Sriastrad					  R128_DST_TILE);
4641.1Sriastrad	dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) |
4651.1Sriastrad					 (dev_priv->span_offset >> 5));
4661.1Sriastrad
4671.2Sriastrad	dev_priv->sarea = drm_legacy_getsarea(dev);
4681.1Sriastrad	if (!dev_priv->sarea) {
4691.1Sriastrad		DRM_ERROR("could not find sarea!\n");
4701.1Sriastrad		dev->dev_private = (void *)dev_priv;
4711.1Sriastrad		r128_do_cleanup_cce(dev);
4721.1Sriastrad		return -EINVAL;
4731.1Sriastrad	}
4741.1Sriastrad
4751.2Sriastrad	dev_priv->mmio = drm_legacy_findmap(dev, init->mmio_offset);
4761.1Sriastrad	if (!dev_priv->mmio) {
4771.1Sriastrad		DRM_ERROR("could not find mmio region!\n");
4781.1Sriastrad		dev->dev_private = (void *)dev_priv;
4791.1Sriastrad		r128_do_cleanup_cce(dev);
4801.1Sriastrad		return -EINVAL;
4811.1Sriastrad	}
4821.2Sriastrad	dev_priv->cce_ring = drm_legacy_findmap(dev, init->ring_offset);
4831.1Sriastrad	if (!dev_priv->cce_ring) {
4841.1Sriastrad		DRM_ERROR("could not find cce ring region!\n");
4851.1Sriastrad		dev->dev_private = (void *)dev_priv;
4861.1Sriastrad		r128_do_cleanup_cce(dev);
4871.1Sriastrad		return -EINVAL;
4881.1Sriastrad	}
4891.2Sriastrad	dev_priv->ring_rptr = drm_legacy_findmap(dev, init->ring_rptr_offset);
4901.1Sriastrad	if (!dev_priv->ring_rptr) {
4911.1Sriastrad		DRM_ERROR("could not find ring read pointer!\n");
4921.1Sriastrad		dev->dev_private = (void *)dev_priv;
4931.1Sriastrad		r128_do_cleanup_cce(dev);
4941.1Sriastrad		return -EINVAL;
4951.1Sriastrad	}
4961.1Sriastrad	dev->agp_buffer_token = init->buffers_offset;
4971.2Sriastrad	dev->agp_buffer_map = drm_legacy_findmap(dev, init->buffers_offset);
4981.1Sriastrad	if (!dev->agp_buffer_map) {
4991.1Sriastrad		DRM_ERROR("could not find dma buffer region!\n");
5001.1Sriastrad		dev->dev_private = (void *)dev_priv;
5011.1Sriastrad		r128_do_cleanup_cce(dev);
5021.1Sriastrad		return -EINVAL;
5031.1Sriastrad	}
5041.1Sriastrad
5051.1Sriastrad	if (!dev_priv->is_pci) {
5061.1Sriastrad		dev_priv->agp_textures =
5071.2Sriastrad		    drm_legacy_findmap(dev, init->agp_textures_offset);
5081.1Sriastrad		if (!dev_priv->agp_textures) {
5091.1Sriastrad			DRM_ERROR("could not find agp texture region!\n");
5101.1Sriastrad			dev->dev_private = (void *)dev_priv;
5111.1Sriastrad			r128_do_cleanup_cce(dev);
5121.1Sriastrad			return -EINVAL;
5131.1Sriastrad		}
5141.1Sriastrad	}
5151.1Sriastrad
5161.1Sriastrad	dev_priv->sarea_priv =
5171.1Sriastrad	    (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle +
5181.1Sriastrad				  init->sarea_priv_offset);
5191.1Sriastrad
5201.2Sriastrad#if IS_ENABLED(CONFIG_AGP)
5211.1Sriastrad	if (!dev_priv->is_pci) {
5221.2Sriastrad		drm_legacy_ioremap_wc(dev_priv->cce_ring, dev);
5231.2Sriastrad		drm_legacy_ioremap_wc(dev_priv->ring_rptr, dev);
5241.2Sriastrad		drm_legacy_ioremap_wc(dev->agp_buffer_map, dev);
5251.1Sriastrad		if (!dev_priv->cce_ring->handle ||
5261.1Sriastrad		    !dev_priv->ring_rptr->handle ||
5271.1Sriastrad		    !dev->agp_buffer_map->handle) {
5281.1Sriastrad			DRM_ERROR("Could not ioremap agp regions!\n");
5291.1Sriastrad			dev->dev_private = (void *)dev_priv;
5301.1Sriastrad			r128_do_cleanup_cce(dev);
5311.1Sriastrad			return -ENOMEM;
5321.1Sriastrad		}
5331.1Sriastrad	} else
5341.1Sriastrad#endif
5351.1Sriastrad	{
5361.1Sriastrad		dev_priv->cce_ring->handle =
5371.1Sriastrad			(void *)(unsigned long)dev_priv->cce_ring->offset;
5381.1Sriastrad		dev_priv->ring_rptr->handle =
5391.1Sriastrad			(void *)(unsigned long)dev_priv->ring_rptr->offset;
5401.1Sriastrad		dev->agp_buffer_map->handle =
5411.1Sriastrad			(void *)(unsigned long)dev->agp_buffer_map->offset;
5421.1Sriastrad	}
5431.1Sriastrad
5441.2Sriastrad#if IS_ENABLED(CONFIG_AGP)
5451.1Sriastrad	if (!dev_priv->is_pci)
5461.1Sriastrad		dev_priv->cce_buffers_offset = dev->agp->base;
5471.1Sriastrad	else
5481.1Sriastrad#endif
5491.1Sriastrad		dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual;
5501.1Sriastrad
5511.1Sriastrad	dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle;
5521.1Sriastrad	dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle
5531.1Sriastrad			      + init->ring_size / sizeof(u32));
5541.1Sriastrad	dev_priv->ring.size = init->ring_size;
5551.2Sriastrad	dev_priv->ring.size_l2qw = order_base_2(init->ring_size / 8);
5561.1Sriastrad
5571.1Sriastrad	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
5581.1Sriastrad
5591.1Sriastrad	dev_priv->ring.high_mark = 128;
5601.1Sriastrad
5611.1Sriastrad	dev_priv->sarea_priv->last_frame = 0;
5621.1Sriastrad	R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);
5631.1Sriastrad
5641.1Sriastrad	dev_priv->sarea_priv->last_dispatch = 0;
5651.1Sriastrad	R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch);
5661.1Sriastrad
5671.2Sriastrad#if IS_ENABLED(CONFIG_AGP)
5681.1Sriastrad	if (dev_priv->is_pci) {
5691.1Sriastrad#endif
5701.1Sriastrad		dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
5711.1Sriastrad		dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
5721.1Sriastrad		dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE;
5731.1Sriastrad		dev_priv->gart_info.addr = NULL;
5741.1Sriastrad		dev_priv->gart_info.bus_addr = 0;
5751.1Sriastrad		dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
5761.3Sriastrad		rc = drm_ati_pcigart_init(dev, &dev_priv->gart_info);
5771.3Sriastrad		if (rc) {
5781.1Sriastrad			DRM_ERROR("failed to init PCI GART!\n");
5791.1Sriastrad			dev->dev_private = (void *)dev_priv;
5801.1Sriastrad			r128_do_cleanup_cce(dev);
5811.3Sriastrad			return rc;
5821.1Sriastrad		}
5831.1Sriastrad		R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr);
5841.2Sriastrad#if IS_ENABLED(CONFIG_AGP)
5851.1Sriastrad	}
5861.1Sriastrad#endif
5871.1Sriastrad
5881.1Sriastrad	r128_cce_init_ring_buffer(dev, dev_priv);
5891.1Sriastrad	rc = r128_cce_load_microcode(dev_priv);
5901.1Sriastrad
5911.1Sriastrad	dev->dev_private = (void *)dev_priv;
5921.1Sriastrad
5931.1Sriastrad	r128_do_engine_reset(dev);
5941.1Sriastrad
5951.1Sriastrad	if (rc) {
5961.1Sriastrad		DRM_ERROR("Failed to load firmware!\n");
5971.1Sriastrad		r128_do_cleanup_cce(dev);
5981.1Sriastrad	}
5991.1Sriastrad
6001.1Sriastrad	return rc;
6011.1Sriastrad}
6021.1Sriastrad
6031.1Sriastradint r128_do_cleanup_cce(struct drm_device *dev)
6041.1Sriastrad{
6051.1Sriastrad
6061.1Sriastrad	/* Make sure interrupts are disabled here because the uninstall ioctl
6071.1Sriastrad	 * may not have been called from userspace and after dev_private
6081.1Sriastrad	 * is freed, it's too late.
6091.1Sriastrad	 */
6101.1Sriastrad	if (dev->irq_enabled)
6111.1Sriastrad		drm_irq_uninstall(dev);
6121.1Sriastrad
6131.1Sriastrad	if (dev->dev_private) {
6141.1Sriastrad		drm_r128_private_t *dev_priv = dev->dev_private;
6151.1Sriastrad
6161.2Sriastrad#if IS_ENABLED(CONFIG_AGP)
6171.1Sriastrad		if (!dev_priv->is_pci) {
6181.1Sriastrad			if (dev_priv->cce_ring != NULL)
6191.2Sriastrad				drm_legacy_ioremapfree(dev_priv->cce_ring, dev);
6201.1Sriastrad			if (dev_priv->ring_rptr != NULL)
6211.2Sriastrad				drm_legacy_ioremapfree(dev_priv->ring_rptr, dev);
6221.1Sriastrad			if (dev->agp_buffer_map != NULL) {
6231.2Sriastrad				drm_legacy_ioremapfree(dev->agp_buffer_map, dev);
6241.1Sriastrad				dev->agp_buffer_map = NULL;
6251.1Sriastrad			}
6261.1Sriastrad		} else
6271.1Sriastrad#endif
6281.1Sriastrad		{
6291.1Sriastrad			if (dev_priv->gart_info.bus_addr)
6301.1Sriastrad				if (!drm_ati_pcigart_cleanup(dev,
6311.1Sriastrad							&dev_priv->gart_info))
6321.1Sriastrad					DRM_ERROR
6331.1Sriastrad					    ("failed to cleanup PCI GART!\n");
6341.1Sriastrad		}
6351.1Sriastrad
6361.1Sriastrad		kfree(dev->dev_private);
6371.1Sriastrad		dev->dev_private = NULL;
6381.1Sriastrad	}
6391.1Sriastrad
6401.1Sriastrad	return 0;
6411.1Sriastrad}
6421.1Sriastrad
6431.1Sriastradint r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
6441.1Sriastrad{
6451.1Sriastrad	drm_r128_init_t *init = data;
6461.1Sriastrad
6471.1Sriastrad	DRM_DEBUG("\n");
6481.1Sriastrad
6491.1Sriastrad	LOCK_TEST_WITH_RETURN(dev, file_priv);
6501.1Sriastrad
6511.1Sriastrad	switch (init->func) {
6521.1Sriastrad	case R128_INIT_CCE:
6531.1Sriastrad		return r128_do_init_cce(dev, init);
6541.1Sriastrad	case R128_CLEANUP_CCE:
6551.1Sriastrad		return r128_do_cleanup_cce(dev);
6561.1Sriastrad	}
6571.1Sriastrad
6581.1Sriastrad	return -EINVAL;
6591.1Sriastrad}
6601.1Sriastrad
6611.1Sriastradint r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv)
6621.1Sriastrad{
6631.1Sriastrad	drm_r128_private_t *dev_priv = dev->dev_private;
6641.1Sriastrad	DRM_DEBUG("\n");
6651.1Sriastrad
6661.1Sriastrad	LOCK_TEST_WITH_RETURN(dev, file_priv);
6671.1Sriastrad
6681.1Sriastrad	DEV_INIT_TEST_WITH_RETURN(dev_priv);
6691.1Sriastrad
6701.1Sriastrad	if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
6711.1Sriastrad		DRM_DEBUG("while CCE running\n");
6721.1Sriastrad		return 0;
6731.1Sriastrad	}
6741.1Sriastrad
6751.1Sriastrad	r128_do_cce_start(dev_priv);
6761.1Sriastrad
6771.1Sriastrad	return 0;
6781.1Sriastrad}
6791.1Sriastrad
6801.1Sriastrad/* Stop the CCE.  The engine must have been idled before calling this
6811.1Sriastrad * routine.
6821.1Sriastrad */
6831.1Sriastradint r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv)
6841.1Sriastrad{
6851.1Sriastrad	drm_r128_private_t *dev_priv = dev->dev_private;
6861.1Sriastrad	drm_r128_cce_stop_t *stop = data;
6871.1Sriastrad	int ret;
6881.1Sriastrad	DRM_DEBUG("\n");
6891.1Sriastrad
6901.1Sriastrad	LOCK_TEST_WITH_RETURN(dev, file_priv);
6911.1Sriastrad
6921.1Sriastrad	DEV_INIT_TEST_WITH_RETURN(dev_priv);
6931.1Sriastrad
6941.1Sriastrad	/* Flush any pending CCE commands.  This ensures any outstanding
6951.1Sriastrad	 * commands are exectuted by the engine before we turn it off.
6961.1Sriastrad	 */
6971.1Sriastrad	if (stop->flush)
6981.1Sriastrad		r128_do_cce_flush(dev_priv);
6991.1Sriastrad
7001.1Sriastrad	/* If we fail to make the engine go idle, we return an error
7011.1Sriastrad	 * code so that the DRM ioctl wrapper can try again.
7021.1Sriastrad	 */
7031.1Sriastrad	if (stop->idle) {
7041.1Sriastrad		ret = r128_do_cce_idle(dev_priv);
7051.1Sriastrad		if (ret)
7061.1Sriastrad			return ret;
7071.1Sriastrad	}
7081.1Sriastrad
7091.1Sriastrad	/* Finally, we can turn off the CCE.  If the engine isn't idle,
7101.1Sriastrad	 * we will get some dropped triangles as they won't be fully
7111.1Sriastrad	 * rendered before the CCE is shut down.
7121.1Sriastrad	 */
7131.1Sriastrad	r128_do_cce_stop(dev_priv);
7141.1Sriastrad
7151.1Sriastrad	/* Reset the engine */
7161.1Sriastrad	r128_do_engine_reset(dev);
7171.1Sriastrad
7181.1Sriastrad	return 0;
7191.1Sriastrad}
7201.1Sriastrad
7211.1Sriastrad/* Just reset the CCE ring.  Called as part of an X Server engine reset.
7221.1Sriastrad */
7231.1Sriastradint r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
7241.1Sriastrad{
7251.1Sriastrad	drm_r128_private_t *dev_priv = dev->dev_private;
7261.1Sriastrad	DRM_DEBUG("\n");
7271.1Sriastrad
7281.1Sriastrad	LOCK_TEST_WITH_RETURN(dev, file_priv);
7291.1Sriastrad
7301.1Sriastrad	DEV_INIT_TEST_WITH_RETURN(dev_priv);
7311.1Sriastrad
7321.1Sriastrad	r128_do_cce_reset(dev_priv);
7331.1Sriastrad
7341.1Sriastrad	/* The CCE is no longer running after an engine reset */
7351.1Sriastrad	dev_priv->cce_running = 0;
7361.1Sriastrad
7371.1Sriastrad	return 0;
7381.1Sriastrad}
7391.1Sriastrad
7401.1Sriastradint r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv)
7411.1Sriastrad{
7421.1Sriastrad	drm_r128_private_t *dev_priv = dev->dev_private;
7431.1Sriastrad	DRM_DEBUG("\n");
7441.1Sriastrad
7451.1Sriastrad	LOCK_TEST_WITH_RETURN(dev, file_priv);
7461.1Sriastrad
7471.1Sriastrad	DEV_INIT_TEST_WITH_RETURN(dev_priv);
7481.1Sriastrad
7491.1Sriastrad	if (dev_priv->cce_running)
7501.1Sriastrad		r128_do_cce_flush(dev_priv);
7511.1Sriastrad
7521.1Sriastrad	return r128_do_cce_idle(dev_priv);
7531.1Sriastrad}
7541.1Sriastrad
7551.1Sriastradint r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
7561.1Sriastrad{
7571.1Sriastrad	DRM_DEBUG("\n");
7581.1Sriastrad
7591.1Sriastrad	LOCK_TEST_WITH_RETURN(dev, file_priv);
7601.1Sriastrad
7611.1Sriastrad	DEV_INIT_TEST_WITH_RETURN(dev->dev_private);
7621.1Sriastrad
7631.1Sriastrad	return r128_do_engine_reset(dev);
7641.1Sriastrad}
7651.1Sriastrad
7661.1Sriastradint r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv)
7671.1Sriastrad{
7681.1Sriastrad	return -EINVAL;
7691.1Sriastrad}
7701.1Sriastrad
7711.1Sriastrad/* ================================================================
7721.1Sriastrad * Freelist management
7731.1Sriastrad */
7741.1Sriastrad#define R128_BUFFER_USED	0xffffffff
7751.1Sriastrad#define R128_BUFFER_FREE	0
7761.1Sriastrad
7771.1Sriastrad#if 0
7781.1Sriastradstatic int r128_freelist_init(struct drm_device *dev)
7791.1Sriastrad{
7801.1Sriastrad	struct drm_device_dma *dma = dev->dma;
7811.1Sriastrad	drm_r128_private_t *dev_priv = dev->dev_private;
7821.1Sriastrad	struct drm_buf *buf;
7831.1Sriastrad	drm_r128_buf_priv_t *buf_priv;
7841.1Sriastrad	drm_r128_freelist_t *entry;
7851.1Sriastrad	int i;
7861.1Sriastrad
7871.1Sriastrad	dev_priv->head = kzalloc(sizeof(drm_r128_freelist_t), GFP_KERNEL);
7881.1Sriastrad	if (dev_priv->head == NULL)
7891.1Sriastrad		return -ENOMEM;
7901.1Sriastrad
7911.1Sriastrad	dev_priv->head->age = R128_BUFFER_USED;
7921.1Sriastrad
7931.1Sriastrad	for (i = 0; i < dma->buf_count; i++) {
7941.1Sriastrad		buf = dma->buflist[i];
7951.1Sriastrad		buf_priv = buf->dev_private;
7961.1Sriastrad
7971.1Sriastrad		entry = kmalloc(sizeof(drm_r128_freelist_t), GFP_KERNEL);
7981.1Sriastrad		if (!entry)
7991.1Sriastrad			return -ENOMEM;
8001.1Sriastrad
8011.1Sriastrad		entry->age = R128_BUFFER_FREE;
8021.1Sriastrad		entry->buf = buf;
8031.1Sriastrad		entry->prev = dev_priv->head;
8041.1Sriastrad		entry->next = dev_priv->head->next;
8051.1Sriastrad		if (!entry->next)
8061.1Sriastrad			dev_priv->tail = entry;
8071.1Sriastrad
8081.1Sriastrad		buf_priv->discard = 0;
8091.1Sriastrad		buf_priv->dispatched = 0;
8101.1Sriastrad		buf_priv->list_entry = entry;
8111.1Sriastrad
8121.1Sriastrad		dev_priv->head->next = entry;
8131.1Sriastrad
8141.1Sriastrad		if (dev_priv->head->next)
8151.1Sriastrad			dev_priv->head->next->prev = entry;
8161.1Sriastrad	}
8171.1Sriastrad
8181.1Sriastrad	return 0;
8191.1Sriastrad
8201.1Sriastrad}
8211.1Sriastrad#endif
8221.1Sriastrad
8231.1Sriastradstatic struct drm_buf *r128_freelist_get(struct drm_device * dev)
8241.1Sriastrad{
8251.1Sriastrad	struct drm_device_dma *dma = dev->dma;
8261.1Sriastrad	drm_r128_private_t *dev_priv = dev->dev_private;
8271.1Sriastrad	drm_r128_buf_priv_t *buf_priv;
8281.1Sriastrad	struct drm_buf *buf;
8291.1Sriastrad	int i, t;
8301.1Sriastrad
8311.1Sriastrad	/* FIXME: Optimize -- use freelist code */
8321.1Sriastrad
8331.1Sriastrad	for (i = 0; i < dma->buf_count; i++) {
8341.1Sriastrad		buf = dma->buflist[i];
8351.1Sriastrad		buf_priv = buf->dev_private;
8361.1Sriastrad		if (!buf->file_priv)
8371.1Sriastrad			return buf;
8381.1Sriastrad	}
8391.1Sriastrad
8401.1Sriastrad	for (t = 0; t < dev_priv->usec_timeout; t++) {
8411.1Sriastrad		u32 done_age = R128_READ(R128_LAST_DISPATCH_REG);
8421.1Sriastrad
8431.1Sriastrad		for (i = 0; i < dma->buf_count; i++) {
8441.1Sriastrad			buf = dma->buflist[i];
8451.1Sriastrad			buf_priv = buf->dev_private;
8461.1Sriastrad			if (buf->pending && buf_priv->age <= done_age) {
8471.1Sriastrad				/* The buffer has been processed, so it
8481.1Sriastrad				 * can now be used.
8491.1Sriastrad				 */
8501.1Sriastrad				buf->pending = 0;
8511.1Sriastrad				return buf;
8521.1Sriastrad			}
8531.1Sriastrad		}
8541.3Sriastrad		udelay(1);
8551.1Sriastrad	}
8561.1Sriastrad
8571.1Sriastrad	DRM_DEBUG("returning NULL!\n");
8581.1Sriastrad	return NULL;
8591.1Sriastrad}
8601.1Sriastrad
8611.1Sriastradvoid r128_freelist_reset(struct drm_device *dev)
8621.1Sriastrad{
8631.1Sriastrad	struct drm_device_dma *dma = dev->dma;
8641.1Sriastrad	int i;
8651.1Sriastrad
8661.1Sriastrad	for (i = 0; i < dma->buf_count; i++) {
8671.1Sriastrad		struct drm_buf *buf = dma->buflist[i];
8681.1Sriastrad		drm_r128_buf_priv_t *buf_priv = buf->dev_private;
8691.1Sriastrad		buf_priv->age = 0;
8701.1Sriastrad	}
8711.1Sriastrad}
8721.1Sriastrad
8731.1Sriastrad/* ================================================================
8741.1Sriastrad * CCE command submission
8751.1Sriastrad */
8761.1Sriastrad
8771.1Sriastradint r128_wait_ring(drm_r128_private_t *dev_priv, int n)
8781.1Sriastrad{
8791.1Sriastrad	drm_r128_ring_buffer_t *ring = &dev_priv->ring;
8801.1Sriastrad	int i;
8811.1Sriastrad
8821.1Sriastrad	for (i = 0; i < dev_priv->usec_timeout; i++) {
8831.1Sriastrad		r128_update_ring_snapshot(dev_priv);
8841.1Sriastrad		if (ring->space >= n)
8851.1Sriastrad			return 0;
8861.3Sriastrad		udelay(1);
8871.1Sriastrad	}
8881.1Sriastrad
8891.1Sriastrad	/* FIXME: This is being ignored... */
8901.1Sriastrad	DRM_ERROR("failed!\n");
8911.1Sriastrad	return -EBUSY;
8921.1Sriastrad}
8931.1Sriastrad
8941.1Sriastradstatic int r128_cce_get_buffers(struct drm_device *dev,
8951.1Sriastrad				struct drm_file *file_priv,
8961.1Sriastrad				struct drm_dma *d)
8971.1Sriastrad{
8981.1Sriastrad	int i;
8991.1Sriastrad	struct drm_buf *buf;
9001.1Sriastrad
9011.1Sriastrad	for (i = d->granted_count; i < d->request_count; i++) {
9021.1Sriastrad		buf = r128_freelist_get(dev);
9031.1Sriastrad		if (!buf)
9041.1Sriastrad			return -EAGAIN;
9051.1Sriastrad
9061.1Sriastrad		buf->file_priv = file_priv;
9071.1Sriastrad
9081.2Sriastrad		if (copy_to_user(&d->request_indices[i], &buf->idx,
9091.1Sriastrad				     sizeof(buf->idx)))
9101.1Sriastrad			return -EFAULT;
9111.2Sriastrad		if (copy_to_user(&d->request_sizes[i], &buf->total,
9121.1Sriastrad				     sizeof(buf->total)))
9131.1Sriastrad			return -EFAULT;
9141.1Sriastrad
9151.1Sriastrad		d->granted_count++;
9161.1Sriastrad	}
9171.1Sriastrad	return 0;
9181.1Sriastrad}
9191.1Sriastrad
9201.1Sriastradint r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv)
9211.1Sriastrad{
9221.1Sriastrad	struct drm_device_dma *dma = dev->dma;
9231.1Sriastrad	int ret = 0;
9241.1Sriastrad	struct drm_dma *d = data;
9251.1Sriastrad
9261.1Sriastrad	LOCK_TEST_WITH_RETURN(dev, file_priv);
9271.1Sriastrad
9281.1Sriastrad	/* Please don't send us buffers.
9291.1Sriastrad	 */
9301.1Sriastrad	if (d->send_count != 0) {
9311.1Sriastrad		DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n",
9321.3Sriastrad			  task_pid_nr(current), d->send_count);
9331.1Sriastrad		return -EINVAL;
9341.1Sriastrad	}
9351.1Sriastrad
9361.1Sriastrad	/* We'll send you buffers.
9371.1Sriastrad	 */
9381.1Sriastrad	if (d->request_count < 0 || d->request_count > dma->buf_count) {
9391.1Sriastrad		DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n",
9401.3Sriastrad			  task_pid_nr(current), d->request_count, dma->buf_count);
9411.1Sriastrad		return -EINVAL;
9421.1Sriastrad	}
9431.1Sriastrad
9441.1Sriastrad	d->granted_count = 0;
9451.1Sriastrad
9461.1Sriastrad	if (d->request_count)
9471.1Sriastrad		ret = r128_cce_get_buffers(dev, file_priv, d);
9481.1Sriastrad
9491.1Sriastrad	return ret;
9501.1Sriastrad}
951