18c2ecf20Sopenharmony_ci/* r128_state.c -- State support for r128 -*- linux-c -*-
28c2ecf20Sopenharmony_ci * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com
38c2ecf20Sopenharmony_ci */
48c2ecf20Sopenharmony_ci/*
58c2ecf20Sopenharmony_ci * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
68c2ecf20Sopenharmony_ci * All Rights Reserved.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
98c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
108c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
118c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
128c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
138c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next
168c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
178c2ecf20Sopenharmony_ci * Software.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
208c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
218c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
228c2ecf20Sopenharmony_ci * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
238c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
248c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
258c2ecf20Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * Authors:
288c2ecf20Sopenharmony_ci *    Gareth Hughes <gareth@valinux.com>
298c2ecf20Sopenharmony_ci */
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#include <linux/pci.h>
328c2ecf20Sopenharmony_ci#include <linux/slab.h>
338c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include <drm/drm_device.h>
368c2ecf20Sopenharmony_ci#include <drm/drm_file.h>
378c2ecf20Sopenharmony_ci#include <drm/drm_print.h>
388c2ecf20Sopenharmony_ci#include <drm/r128_drm.h>
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#include "r128_drv.h"
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* ================================================================
438c2ecf20Sopenharmony_ci * CCE hardware state programming functions
448c2ecf20Sopenharmony_ci */
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistatic void r128_emit_clip_rects(drm_r128_private_t *dev_priv,
478c2ecf20Sopenharmony_ci				 struct drm_clip_rect *boxes, int count)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	u32 aux_sc_cntl = 0x00000000;
508c2ecf20Sopenharmony_ci	RING_LOCALS;
518c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	BEGIN_RING((count < 3 ? count : 3) * 5 + 2);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	if (count >= 1) {
568c2ecf20Sopenharmony_ci		OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3));
578c2ecf20Sopenharmony_ci		OUT_RING(boxes[0].x1);
588c2ecf20Sopenharmony_ci		OUT_RING(boxes[0].x2 - 1);
598c2ecf20Sopenharmony_ci		OUT_RING(boxes[0].y1);
608c2ecf20Sopenharmony_ci		OUT_RING(boxes[0].y2 - 1);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci		aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR);
638c2ecf20Sopenharmony_ci	}
648c2ecf20Sopenharmony_ci	if (count >= 2) {
658c2ecf20Sopenharmony_ci		OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3));
668c2ecf20Sopenharmony_ci		OUT_RING(boxes[1].x1);
678c2ecf20Sopenharmony_ci		OUT_RING(boxes[1].x2 - 1);
688c2ecf20Sopenharmony_ci		OUT_RING(boxes[1].y1);
698c2ecf20Sopenharmony_ci		OUT_RING(boxes[1].y2 - 1);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci		aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR);
728c2ecf20Sopenharmony_ci	}
738c2ecf20Sopenharmony_ci	if (count >= 3) {
748c2ecf20Sopenharmony_ci		OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3));
758c2ecf20Sopenharmony_ci		OUT_RING(boxes[2].x1);
768c2ecf20Sopenharmony_ci		OUT_RING(boxes[2].x2 - 1);
778c2ecf20Sopenharmony_ci		OUT_RING(boxes[2].y1);
788c2ecf20Sopenharmony_ci		OUT_RING(boxes[2].y2 - 1);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci		aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR);
818c2ecf20Sopenharmony_ci	}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0));
848c2ecf20Sopenharmony_ci	OUT_RING(aux_sc_cntl);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	ADVANCE_RING();
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic __inline__ void r128_emit_core(drm_r128_private_t *dev_priv)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
928c2ecf20Sopenharmony_ci	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
938c2ecf20Sopenharmony_ci	RING_LOCALS;
948c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	BEGIN_RING(2);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0));
998c2ecf20Sopenharmony_ci	OUT_RING(ctx->scale_3d_cntl);
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	ADVANCE_RING();
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic __inline__ void r128_emit_context(drm_r128_private_t *dev_priv)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1078c2ecf20Sopenharmony_ci	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
1088c2ecf20Sopenharmony_ci	RING_LOCALS;
1098c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	BEGIN_RING(13);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11));
1148c2ecf20Sopenharmony_ci	OUT_RING(ctx->dst_pitch_offset_c);
1158c2ecf20Sopenharmony_ci	OUT_RING(ctx->dp_gui_master_cntl_c);
1168c2ecf20Sopenharmony_ci	OUT_RING(ctx->sc_top_left_c);
1178c2ecf20Sopenharmony_ci	OUT_RING(ctx->sc_bottom_right_c);
1188c2ecf20Sopenharmony_ci	OUT_RING(ctx->z_offset_c);
1198c2ecf20Sopenharmony_ci	OUT_RING(ctx->z_pitch_c);
1208c2ecf20Sopenharmony_ci	OUT_RING(ctx->z_sten_cntl_c);
1218c2ecf20Sopenharmony_ci	OUT_RING(ctx->tex_cntl_c);
1228c2ecf20Sopenharmony_ci	OUT_RING(ctx->misc_3d_state_cntl_reg);
1238c2ecf20Sopenharmony_ci	OUT_RING(ctx->texture_clr_cmp_clr_c);
1248c2ecf20Sopenharmony_ci	OUT_RING(ctx->texture_clr_cmp_msk_c);
1258c2ecf20Sopenharmony_ci	OUT_RING(ctx->fog_color_c);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	ADVANCE_RING();
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistatic __inline__ void r128_emit_setup(drm_r128_private_t *dev_priv)
1318c2ecf20Sopenharmony_ci{
1328c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1338c2ecf20Sopenharmony_ci	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
1348c2ecf20Sopenharmony_ci	RING_LOCALS;
1358c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	BEGIN_RING(3);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP));
1408c2ecf20Sopenharmony_ci	OUT_RING(ctx->setup_cntl);
1418c2ecf20Sopenharmony_ci	OUT_RING(ctx->pm4_vc_fpu_setup);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	ADVANCE_RING();
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic __inline__ void r128_emit_masks(drm_r128_private_t *dev_priv)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1498c2ecf20Sopenharmony_ci	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
1508c2ecf20Sopenharmony_ci	RING_LOCALS;
1518c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	BEGIN_RING(5);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
1568c2ecf20Sopenharmony_ci	OUT_RING(ctx->dp_write_mask);
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1));
1598c2ecf20Sopenharmony_ci	OUT_RING(ctx->sten_ref_mask_c);
1608c2ecf20Sopenharmony_ci	OUT_RING(ctx->plane_3d_mask_c);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	ADVANCE_RING();
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic __inline__ void r128_emit_window(drm_r128_private_t *dev_priv)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1688c2ecf20Sopenharmony_ci	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
1698c2ecf20Sopenharmony_ci	RING_LOCALS;
1708c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	BEGIN_RING(2);
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0));
1758c2ecf20Sopenharmony_ci	OUT_RING(ctx->window_xy_offset);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	ADVANCE_RING();
1788c2ecf20Sopenharmony_ci}
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic __inline__ void r128_emit_tex0(drm_r128_private_t *dev_priv)
1818c2ecf20Sopenharmony_ci{
1828c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
1838c2ecf20Sopenharmony_ci	drm_r128_context_regs_t *ctx = &sarea_priv->context_state;
1848c2ecf20Sopenharmony_ci	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0];
1858c2ecf20Sopenharmony_ci	int i;
1868c2ecf20Sopenharmony_ci	RING_LOCALS;
1878c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C,
1928c2ecf20Sopenharmony_ci			     2 + R128_MAX_TEXTURE_LEVELS));
1938c2ecf20Sopenharmony_ci	OUT_RING(tex->tex_cntl);
1948c2ecf20Sopenharmony_ci	OUT_RING(tex->tex_combine_cntl);
1958c2ecf20Sopenharmony_ci	OUT_RING(ctx->tex_size_pitch_c);
1968c2ecf20Sopenharmony_ci	for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++)
1978c2ecf20Sopenharmony_ci		OUT_RING(tex->tex_offset[i]);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1));
2008c2ecf20Sopenharmony_ci	OUT_RING(ctx->constant_color_c);
2018c2ecf20Sopenharmony_ci	OUT_RING(tex->tex_border_color);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	ADVANCE_RING();
2048c2ecf20Sopenharmony_ci}
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_cistatic __inline__ void r128_emit_tex1(drm_r128_private_t *dev_priv)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
2098c2ecf20Sopenharmony_ci	drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1];
2108c2ecf20Sopenharmony_ci	int i;
2118c2ecf20Sopenharmony_ci	RING_LOCALS;
2128c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS));
2178c2ecf20Sopenharmony_ci	OUT_RING(tex->tex_cntl);
2188c2ecf20Sopenharmony_ci	OUT_RING(tex->tex_combine_cntl);
2198c2ecf20Sopenharmony_ci	for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++)
2208c2ecf20Sopenharmony_ci		OUT_RING(tex->tex_offset[i]);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0));
2238c2ecf20Sopenharmony_ci	OUT_RING(tex->tex_border_color);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	ADVANCE_RING();
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cistatic void r128_emit_state(drm_r128_private_t *dev_priv)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
2318c2ecf20Sopenharmony_ci	unsigned int dirty = sarea_priv->dirty;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	DRM_DEBUG("dirty=0x%08x\n", dirty);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (dirty & R128_UPLOAD_CORE) {
2368c2ecf20Sopenharmony_ci		r128_emit_core(dev_priv);
2378c2ecf20Sopenharmony_ci		sarea_priv->dirty &= ~R128_UPLOAD_CORE;
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	if (dirty & R128_UPLOAD_CONTEXT) {
2418c2ecf20Sopenharmony_ci		r128_emit_context(dev_priv);
2428c2ecf20Sopenharmony_ci		sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT;
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	if (dirty & R128_UPLOAD_SETUP) {
2468c2ecf20Sopenharmony_ci		r128_emit_setup(dev_priv);
2478c2ecf20Sopenharmony_ci		sarea_priv->dirty &= ~R128_UPLOAD_SETUP;
2488c2ecf20Sopenharmony_ci	}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	if (dirty & R128_UPLOAD_MASKS) {
2518c2ecf20Sopenharmony_ci		r128_emit_masks(dev_priv);
2528c2ecf20Sopenharmony_ci		sarea_priv->dirty &= ~R128_UPLOAD_MASKS;
2538c2ecf20Sopenharmony_ci	}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	if (dirty & R128_UPLOAD_WINDOW) {
2568c2ecf20Sopenharmony_ci		r128_emit_window(dev_priv);
2578c2ecf20Sopenharmony_ci		sarea_priv->dirty &= ~R128_UPLOAD_WINDOW;
2588c2ecf20Sopenharmony_ci	}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	if (dirty & R128_UPLOAD_TEX0) {
2618c2ecf20Sopenharmony_ci		r128_emit_tex0(dev_priv);
2628c2ecf20Sopenharmony_ci		sarea_priv->dirty &= ~R128_UPLOAD_TEX0;
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	if (dirty & R128_UPLOAD_TEX1) {
2668c2ecf20Sopenharmony_ci		r128_emit_tex1(dev_priv);
2678c2ecf20Sopenharmony_ci		sarea_priv->dirty &= ~R128_UPLOAD_TEX1;
2688c2ecf20Sopenharmony_ci	}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	/* Turn off the texture cache flushing */
2718c2ecf20Sopenharmony_ci	sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE;
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci#if R128_PERFORMANCE_BOXES
2778c2ecf20Sopenharmony_ci/* ================================================================
2788c2ecf20Sopenharmony_ci * Performance monitoring functions
2798c2ecf20Sopenharmony_ci */
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_cistatic void r128_clear_box(drm_r128_private_t *dev_priv,
2828c2ecf20Sopenharmony_ci			   int x, int y, int w, int h, int r, int g, int b)
2838c2ecf20Sopenharmony_ci{
2848c2ecf20Sopenharmony_ci	u32 pitch, offset;
2858c2ecf20Sopenharmony_ci	u32 fb_bpp, color;
2868c2ecf20Sopenharmony_ci	RING_LOCALS;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	switch (dev_priv->fb_bpp) {
2898c2ecf20Sopenharmony_ci	case 16:
2908c2ecf20Sopenharmony_ci		fb_bpp = R128_GMC_DST_16BPP;
2918c2ecf20Sopenharmony_ci		color = (((r & 0xf8) << 8) |
2928c2ecf20Sopenharmony_ci			 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
2938c2ecf20Sopenharmony_ci		break;
2948c2ecf20Sopenharmony_ci	case 24:
2958c2ecf20Sopenharmony_ci		fb_bpp = R128_GMC_DST_24BPP;
2968c2ecf20Sopenharmony_ci		color = ((r << 16) | (g << 8) | b);
2978c2ecf20Sopenharmony_ci		break;
2988c2ecf20Sopenharmony_ci	case 32:
2998c2ecf20Sopenharmony_ci		fb_bpp = R128_GMC_DST_32BPP;
3008c2ecf20Sopenharmony_ci		color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
3018c2ecf20Sopenharmony_ci		break;
3028c2ecf20Sopenharmony_ci	default:
3038c2ecf20Sopenharmony_ci		return;
3048c2ecf20Sopenharmony_ci	}
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	offset = dev_priv->back_offset;
3078c2ecf20Sopenharmony_ci	pitch = dev_priv->back_pitch >> 3;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	BEGIN_RING(6);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
3128c2ecf20Sopenharmony_ci	OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
3138c2ecf20Sopenharmony_ci		 R128_GMC_BRUSH_SOLID_COLOR |
3148c2ecf20Sopenharmony_ci		 fb_bpp |
3158c2ecf20Sopenharmony_ci		 R128_GMC_SRC_DATATYPE_COLOR |
3168c2ecf20Sopenharmony_ci		 R128_ROP3_P |
3178c2ecf20Sopenharmony_ci		 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS);
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	OUT_RING((pitch << 21) | (offset >> 5));
3208c2ecf20Sopenharmony_ci	OUT_RING(color);
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	OUT_RING((x << 16) | y);
3238c2ecf20Sopenharmony_ci	OUT_RING((w << 16) | h);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	ADVANCE_RING();
3268c2ecf20Sopenharmony_ci}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_cistatic void r128_cce_performance_boxes(drm_r128_private_t *dev_priv)
3298c2ecf20Sopenharmony_ci{
3308c2ecf20Sopenharmony_ci	if (atomic_read(&dev_priv->idle_count) == 0)
3318c2ecf20Sopenharmony_ci		r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
3328c2ecf20Sopenharmony_ci	else
3338c2ecf20Sopenharmony_ci		atomic_set(&dev_priv->idle_count, 0);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci#endif
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci/* ================================================================
3398c2ecf20Sopenharmony_ci * CCE command dispatch functions
3408c2ecf20Sopenharmony_ci */
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_cistatic void r128_print_dirty(const char *msg, unsigned int flags)
3438c2ecf20Sopenharmony_ci{
3448c2ecf20Sopenharmony_ci	DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
3458c2ecf20Sopenharmony_ci		 msg,
3468c2ecf20Sopenharmony_ci		 flags,
3478c2ecf20Sopenharmony_ci		 (flags & R128_UPLOAD_CORE) ? "core, " : "",
3488c2ecf20Sopenharmony_ci		 (flags & R128_UPLOAD_CONTEXT) ? "context, " : "",
3498c2ecf20Sopenharmony_ci		 (flags & R128_UPLOAD_SETUP) ? "setup, " : "",
3508c2ecf20Sopenharmony_ci		 (flags & R128_UPLOAD_TEX0) ? "tex0, " : "",
3518c2ecf20Sopenharmony_ci		 (flags & R128_UPLOAD_TEX1) ? "tex1, " : "",
3528c2ecf20Sopenharmony_ci		 (flags & R128_UPLOAD_MASKS) ? "masks, " : "",
3538c2ecf20Sopenharmony_ci		 (flags & R128_UPLOAD_WINDOW) ? "window, " : "",
3548c2ecf20Sopenharmony_ci		 (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "",
3558c2ecf20Sopenharmony_ci		 (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "");
3568c2ecf20Sopenharmony_ci}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cistatic void r128_cce_dispatch_clear(struct drm_device *dev,
3598c2ecf20Sopenharmony_ci				    drm_r128_clear_t *clear)
3608c2ecf20Sopenharmony_ci{
3618c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
3628c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
3638c2ecf20Sopenharmony_ci	int nbox = sarea_priv->nbox;
3648c2ecf20Sopenharmony_ci	struct drm_clip_rect *pbox = sarea_priv->boxes;
3658c2ecf20Sopenharmony_ci	unsigned int flags = clear->flags;
3668c2ecf20Sopenharmony_ci	int i;
3678c2ecf20Sopenharmony_ci	RING_LOCALS;
3688c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	if (dev_priv->page_flipping && dev_priv->current_page == 1) {
3718c2ecf20Sopenharmony_ci		unsigned int tmp = flags;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci		flags &= ~(R128_FRONT | R128_BACK);
3748c2ecf20Sopenharmony_ci		if (tmp & R128_FRONT)
3758c2ecf20Sopenharmony_ci			flags |= R128_BACK;
3768c2ecf20Sopenharmony_ci		if (tmp & R128_BACK)
3778c2ecf20Sopenharmony_ci			flags |= R128_FRONT;
3788c2ecf20Sopenharmony_ci	}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	for (i = 0; i < nbox; i++) {
3818c2ecf20Sopenharmony_ci		int x = pbox[i].x1;
3828c2ecf20Sopenharmony_ci		int y = pbox[i].y1;
3838c2ecf20Sopenharmony_ci		int w = pbox[i].x2 - x;
3848c2ecf20Sopenharmony_ci		int h = pbox[i].y2 - y;
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ci		DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n",
3878c2ecf20Sopenharmony_ci			  pbox[i].x1, pbox[i].y1, pbox[i].x2,
3888c2ecf20Sopenharmony_ci			  pbox[i].y2, flags);
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci		if (flags & (R128_FRONT | R128_BACK)) {
3918c2ecf20Sopenharmony_ci			BEGIN_RING(2);
3928c2ecf20Sopenharmony_ci
3938c2ecf20Sopenharmony_ci			OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0));
3948c2ecf20Sopenharmony_ci			OUT_RING(clear->color_mask);
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci			ADVANCE_RING();
3978c2ecf20Sopenharmony_ci		}
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci		if (flags & R128_FRONT) {
4008c2ecf20Sopenharmony_ci			BEGIN_RING(6);
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
4038c2ecf20Sopenharmony_ci			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
4048c2ecf20Sopenharmony_ci				 R128_GMC_BRUSH_SOLID_COLOR |
4058c2ecf20Sopenharmony_ci				 (dev_priv->color_fmt << 8) |
4068c2ecf20Sopenharmony_ci				 R128_GMC_SRC_DATATYPE_COLOR |
4078c2ecf20Sopenharmony_ci				 R128_ROP3_P |
4088c2ecf20Sopenharmony_ci				 R128_GMC_CLR_CMP_CNTL_DIS |
4098c2ecf20Sopenharmony_ci				 R128_GMC_AUX_CLIP_DIS);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci			OUT_RING(dev_priv->front_pitch_offset_c);
4128c2ecf20Sopenharmony_ci			OUT_RING(clear->clear_color);
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci			OUT_RING((x << 16) | y);
4158c2ecf20Sopenharmony_ci			OUT_RING((w << 16) | h);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci			ADVANCE_RING();
4188c2ecf20Sopenharmony_ci		}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci		if (flags & R128_BACK) {
4218c2ecf20Sopenharmony_ci			BEGIN_RING(6);
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ci			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
4248c2ecf20Sopenharmony_ci			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
4258c2ecf20Sopenharmony_ci				 R128_GMC_BRUSH_SOLID_COLOR |
4268c2ecf20Sopenharmony_ci				 (dev_priv->color_fmt << 8) |
4278c2ecf20Sopenharmony_ci				 R128_GMC_SRC_DATATYPE_COLOR |
4288c2ecf20Sopenharmony_ci				 R128_ROP3_P |
4298c2ecf20Sopenharmony_ci				 R128_GMC_CLR_CMP_CNTL_DIS |
4308c2ecf20Sopenharmony_ci				 R128_GMC_AUX_CLIP_DIS);
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci			OUT_RING(dev_priv->back_pitch_offset_c);
4338c2ecf20Sopenharmony_ci			OUT_RING(clear->clear_color);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci			OUT_RING((x << 16) | y);
4368c2ecf20Sopenharmony_ci			OUT_RING((w << 16) | h);
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci			ADVANCE_RING();
4398c2ecf20Sopenharmony_ci		}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci		if (flags & R128_DEPTH) {
4428c2ecf20Sopenharmony_ci			BEGIN_RING(6);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
4458c2ecf20Sopenharmony_ci			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
4468c2ecf20Sopenharmony_ci				 R128_GMC_BRUSH_SOLID_COLOR |
4478c2ecf20Sopenharmony_ci				 (dev_priv->depth_fmt << 8) |
4488c2ecf20Sopenharmony_ci				 R128_GMC_SRC_DATATYPE_COLOR |
4498c2ecf20Sopenharmony_ci				 R128_ROP3_P |
4508c2ecf20Sopenharmony_ci				 R128_GMC_CLR_CMP_CNTL_DIS |
4518c2ecf20Sopenharmony_ci				 R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci			OUT_RING(dev_priv->depth_pitch_offset_c);
4548c2ecf20Sopenharmony_ci			OUT_RING(clear->clear_depth);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci			OUT_RING((x << 16) | y);
4578c2ecf20Sopenharmony_ci			OUT_RING((w << 16) | h);
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci			ADVANCE_RING();
4608c2ecf20Sopenharmony_ci		}
4618c2ecf20Sopenharmony_ci	}
4628c2ecf20Sopenharmony_ci}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_cistatic void r128_cce_dispatch_swap(struct drm_device *dev)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
4678c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
4688c2ecf20Sopenharmony_ci	int nbox = sarea_priv->nbox;
4698c2ecf20Sopenharmony_ci	struct drm_clip_rect *pbox = sarea_priv->boxes;
4708c2ecf20Sopenharmony_ci	int i;
4718c2ecf20Sopenharmony_ci	RING_LOCALS;
4728c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci#if R128_PERFORMANCE_BOXES
4758c2ecf20Sopenharmony_ci	/* Do some trivial performance monitoring...
4768c2ecf20Sopenharmony_ci	 */
4778c2ecf20Sopenharmony_ci	r128_cce_performance_boxes(dev_priv);
4788c2ecf20Sopenharmony_ci#endif
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	for (i = 0; i < nbox; i++) {
4818c2ecf20Sopenharmony_ci		int x = pbox[i].x1;
4828c2ecf20Sopenharmony_ci		int y = pbox[i].y1;
4838c2ecf20Sopenharmony_ci		int w = pbox[i].x2 - x;
4848c2ecf20Sopenharmony_ci		int h = pbox[i].y2 - y;
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci		BEGIN_RING(7);
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci		OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
4898c2ecf20Sopenharmony_ci		OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
4908c2ecf20Sopenharmony_ci			 R128_GMC_DST_PITCH_OFFSET_CNTL |
4918c2ecf20Sopenharmony_ci			 R128_GMC_BRUSH_NONE |
4928c2ecf20Sopenharmony_ci			 (dev_priv->color_fmt << 8) |
4938c2ecf20Sopenharmony_ci			 R128_GMC_SRC_DATATYPE_COLOR |
4948c2ecf20Sopenharmony_ci			 R128_ROP3_S |
4958c2ecf20Sopenharmony_ci			 R128_DP_SRC_SOURCE_MEMORY |
4968c2ecf20Sopenharmony_ci			 R128_GMC_CLR_CMP_CNTL_DIS |
4978c2ecf20Sopenharmony_ci			 R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci		/* Make this work even if front & back are flipped:
5008c2ecf20Sopenharmony_ci		 */
5018c2ecf20Sopenharmony_ci		if (dev_priv->current_page == 0) {
5028c2ecf20Sopenharmony_ci			OUT_RING(dev_priv->back_pitch_offset_c);
5038c2ecf20Sopenharmony_ci			OUT_RING(dev_priv->front_pitch_offset_c);
5048c2ecf20Sopenharmony_ci		} else {
5058c2ecf20Sopenharmony_ci			OUT_RING(dev_priv->front_pitch_offset_c);
5068c2ecf20Sopenharmony_ci			OUT_RING(dev_priv->back_pitch_offset_c);
5078c2ecf20Sopenharmony_ci		}
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci		OUT_RING((x << 16) | y);
5108c2ecf20Sopenharmony_ci		OUT_RING((x << 16) | y);
5118c2ecf20Sopenharmony_ci		OUT_RING((w << 16) | h);
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci		ADVANCE_RING();
5148c2ecf20Sopenharmony_ci	}
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	/* Increment the frame counter.  The client-side 3D driver must
5178c2ecf20Sopenharmony_ci	 * throttle the framerate by waiting for this value before
5188c2ecf20Sopenharmony_ci	 * performing the swapbuffer ioctl.
5198c2ecf20Sopenharmony_ci	 */
5208c2ecf20Sopenharmony_ci	dev_priv->sarea_priv->last_frame++;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	BEGIN_RING(2);
5238c2ecf20Sopenharmony_ci
5248c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
5258c2ecf20Sopenharmony_ci	OUT_RING(dev_priv->sarea_priv->last_frame);
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	ADVANCE_RING();
5288c2ecf20Sopenharmony_ci}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_cistatic void r128_cce_dispatch_flip(struct drm_device *dev)
5318c2ecf20Sopenharmony_ci{
5328c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
5338c2ecf20Sopenharmony_ci	RING_LOCALS;
5348c2ecf20Sopenharmony_ci	DRM_DEBUG("page=%d pfCurrentPage=%d\n",
5358c2ecf20Sopenharmony_ci		  dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage);
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci#if R128_PERFORMANCE_BOXES
5388c2ecf20Sopenharmony_ci	/* Do some trivial performance monitoring...
5398c2ecf20Sopenharmony_ci	 */
5408c2ecf20Sopenharmony_ci	r128_cce_performance_boxes(dev_priv);
5418c2ecf20Sopenharmony_ci#endif
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	BEGIN_RING(4);
5448c2ecf20Sopenharmony_ci
5458c2ecf20Sopenharmony_ci	R128_WAIT_UNTIL_PAGE_FLIPPED();
5468c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0));
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	if (dev_priv->current_page == 0)
5498c2ecf20Sopenharmony_ci		OUT_RING(dev_priv->back_offset);
5508c2ecf20Sopenharmony_ci	else
5518c2ecf20Sopenharmony_ci		OUT_RING(dev_priv->front_offset);
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	ADVANCE_RING();
5548c2ecf20Sopenharmony_ci
5558c2ecf20Sopenharmony_ci	/* Increment the frame counter.  The client-side 3D driver must
5568c2ecf20Sopenharmony_ci	 * throttle the framerate by waiting for this value before
5578c2ecf20Sopenharmony_ci	 * performing the swapbuffer ioctl.
5588c2ecf20Sopenharmony_ci	 */
5598c2ecf20Sopenharmony_ci	dev_priv->sarea_priv->last_frame++;
5608c2ecf20Sopenharmony_ci	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page =
5618c2ecf20Sopenharmony_ci	    1 - dev_priv->current_page;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	BEGIN_RING(2);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0));
5668c2ecf20Sopenharmony_ci	OUT_RING(dev_priv->sarea_priv->last_frame);
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	ADVANCE_RING();
5698c2ecf20Sopenharmony_ci}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_cistatic void r128_cce_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf)
5728c2ecf20Sopenharmony_ci{
5738c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
5748c2ecf20Sopenharmony_ci	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
5758c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
5768c2ecf20Sopenharmony_ci	int format = sarea_priv->vc_format;
5778c2ecf20Sopenharmony_ci	int offset = buf->bus_address;
5788c2ecf20Sopenharmony_ci	int size = buf->used;
5798c2ecf20Sopenharmony_ci	int prim = buf_priv->prim;
5808c2ecf20Sopenharmony_ci	int i = 0;
5818c2ecf20Sopenharmony_ci	RING_LOCALS;
5828c2ecf20Sopenharmony_ci	DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox);
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	if (0)
5858c2ecf20Sopenharmony_ci		r128_print_dirty("dispatch_vertex", sarea_priv->dirty);
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci	if (buf->used) {
5888c2ecf20Sopenharmony_ci		buf_priv->dispatched = 1;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci		if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS)
5918c2ecf20Sopenharmony_ci			r128_emit_state(dev_priv);
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci		do {
5948c2ecf20Sopenharmony_ci			/* Emit the next set of up to three cliprects */
5958c2ecf20Sopenharmony_ci			if (i < sarea_priv->nbox) {
5968c2ecf20Sopenharmony_ci				r128_emit_clip_rects(dev_priv,
5978c2ecf20Sopenharmony_ci						     &sarea_priv->boxes[i],
5988c2ecf20Sopenharmony_ci						     sarea_priv->nbox - i);
5998c2ecf20Sopenharmony_ci			}
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci			/* Emit the vertex buffer rendering commands */
6028c2ecf20Sopenharmony_ci			BEGIN_RING(5);
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci			OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3));
6058c2ecf20Sopenharmony_ci			OUT_RING(offset);
6068c2ecf20Sopenharmony_ci			OUT_RING(size);
6078c2ecf20Sopenharmony_ci			OUT_RING(format);
6088c2ecf20Sopenharmony_ci			OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST |
6098c2ecf20Sopenharmony_ci				 (size << R128_CCE_VC_CNTL_NUM_SHIFT));
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci			ADVANCE_RING();
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci			i += 3;
6148c2ecf20Sopenharmony_ci		} while (i < sarea_priv->nbox);
6158c2ecf20Sopenharmony_ci	}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	if (buf_priv->discard) {
6188c2ecf20Sopenharmony_ci		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci		/* Emit the vertex buffer age */
6218c2ecf20Sopenharmony_ci		BEGIN_RING(2);
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci		OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
6248c2ecf20Sopenharmony_ci		OUT_RING(buf_priv->age);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci		ADVANCE_RING();
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci		buf->pending = 1;
6298c2ecf20Sopenharmony_ci		buf->used = 0;
6308c2ecf20Sopenharmony_ci		/* FIXME: Check dispatched field */
6318c2ecf20Sopenharmony_ci		buf_priv->dispatched = 0;
6328c2ecf20Sopenharmony_ci	}
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	dev_priv->sarea_priv->last_dispatch++;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
6378c2ecf20Sopenharmony_ci	sarea_priv->nbox = 0;
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_cistatic void r128_cce_dispatch_indirect(struct drm_device *dev,
6418c2ecf20Sopenharmony_ci				       struct drm_buf *buf, int start, int end)
6428c2ecf20Sopenharmony_ci{
6438c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
6448c2ecf20Sopenharmony_ci	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
6458c2ecf20Sopenharmony_ci	RING_LOCALS;
6468c2ecf20Sopenharmony_ci	DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end);
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	if (start != end) {
6498c2ecf20Sopenharmony_ci		int offset = buf->bus_address + start;
6508c2ecf20Sopenharmony_ci		int dwords = (end - start + 3) / sizeof(u32);
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci		/* Indirect buffer data must be an even number of
6538c2ecf20Sopenharmony_ci		 * dwords, so if we've been given an odd number we must
6548c2ecf20Sopenharmony_ci		 * pad the data with a Type-2 CCE packet.
6558c2ecf20Sopenharmony_ci		 */
6568c2ecf20Sopenharmony_ci		if (dwords & 1) {
6578c2ecf20Sopenharmony_ci			u32 *data = (u32 *)
6588c2ecf20Sopenharmony_ci			    ((char *)dev->agp_buffer_map->handle
6598c2ecf20Sopenharmony_ci			     + buf->offset + start);
6608c2ecf20Sopenharmony_ci			data[dwords++] = cpu_to_le32(R128_CCE_PACKET2);
6618c2ecf20Sopenharmony_ci		}
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci		buf_priv->dispatched = 1;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci		/* Fire off the indirect buffer */
6668c2ecf20Sopenharmony_ci		BEGIN_RING(3);
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci		OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1));
6698c2ecf20Sopenharmony_ci		OUT_RING(offset);
6708c2ecf20Sopenharmony_ci		OUT_RING(dwords);
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci		ADVANCE_RING();
6738c2ecf20Sopenharmony_ci	}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci	if (buf_priv->discard) {
6768c2ecf20Sopenharmony_ci		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci		/* Emit the indirect buffer age */
6798c2ecf20Sopenharmony_ci		BEGIN_RING(2);
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci		OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
6828c2ecf20Sopenharmony_ci		OUT_RING(buf_priv->age);
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci		ADVANCE_RING();
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci		buf->pending = 1;
6878c2ecf20Sopenharmony_ci		buf->used = 0;
6888c2ecf20Sopenharmony_ci		/* FIXME: Check dispatched field */
6898c2ecf20Sopenharmony_ci		buf_priv->dispatched = 0;
6908c2ecf20Sopenharmony_ci	}
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	dev_priv->sarea_priv->last_dispatch++;
6938c2ecf20Sopenharmony_ci}
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_cistatic void r128_cce_dispatch_indices(struct drm_device *dev,
6968c2ecf20Sopenharmony_ci				      struct drm_buf *buf,
6978c2ecf20Sopenharmony_ci				      int start, int end, int count)
6988c2ecf20Sopenharmony_ci{
6998c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
7008c2ecf20Sopenharmony_ci	drm_r128_buf_priv_t *buf_priv = buf->dev_private;
7018c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
7028c2ecf20Sopenharmony_ci	int format = sarea_priv->vc_format;
7038c2ecf20Sopenharmony_ci	int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset;
7048c2ecf20Sopenharmony_ci	int prim = buf_priv->prim;
7058c2ecf20Sopenharmony_ci	u32 *data;
7068c2ecf20Sopenharmony_ci	int dwords;
7078c2ecf20Sopenharmony_ci	int i = 0;
7088c2ecf20Sopenharmony_ci	RING_LOCALS;
7098c2ecf20Sopenharmony_ci	DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count);
7108c2ecf20Sopenharmony_ci
7118c2ecf20Sopenharmony_ci	if (0)
7128c2ecf20Sopenharmony_ci		r128_print_dirty("dispatch_indices", sarea_priv->dirty);
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	if (start != end) {
7158c2ecf20Sopenharmony_ci		buf_priv->dispatched = 1;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci		if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS)
7188c2ecf20Sopenharmony_ci			r128_emit_state(dev_priv);
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci		dwords = (end - start + 3) / sizeof(u32);
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci		data = (u32 *) ((char *)dev->agp_buffer_map->handle
7238c2ecf20Sopenharmony_ci				+ buf->offset + start);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci		data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM,
7268c2ecf20Sopenharmony_ci						  dwords - 2));
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci		data[1] = cpu_to_le32(offset);
7298c2ecf20Sopenharmony_ci		data[2] = cpu_to_le32(R128_MAX_VB_VERTS);
7308c2ecf20Sopenharmony_ci		data[3] = cpu_to_le32(format);
7318c2ecf20Sopenharmony_ci		data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND |
7328c2ecf20Sopenharmony_ci				       (count << 16)));
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci		if (count & 0x1) {
7358c2ecf20Sopenharmony_ci#ifdef __LITTLE_ENDIAN
7368c2ecf20Sopenharmony_ci			data[dwords - 1] &= 0x0000ffff;
7378c2ecf20Sopenharmony_ci#else
7388c2ecf20Sopenharmony_ci			data[dwords - 1] &= 0xffff0000;
7398c2ecf20Sopenharmony_ci#endif
7408c2ecf20Sopenharmony_ci		}
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci		do {
7438c2ecf20Sopenharmony_ci			/* Emit the next set of up to three cliprects */
7448c2ecf20Sopenharmony_ci			if (i < sarea_priv->nbox) {
7458c2ecf20Sopenharmony_ci				r128_emit_clip_rects(dev_priv,
7468c2ecf20Sopenharmony_ci						     &sarea_priv->boxes[i],
7478c2ecf20Sopenharmony_ci						     sarea_priv->nbox - i);
7488c2ecf20Sopenharmony_ci			}
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci			r128_cce_dispatch_indirect(dev, buf, start, end);
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci			i += 3;
7538c2ecf20Sopenharmony_ci		} while (i < sarea_priv->nbox);
7548c2ecf20Sopenharmony_ci	}
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci	if (buf_priv->discard) {
7578c2ecf20Sopenharmony_ci		buf_priv->age = dev_priv->sarea_priv->last_dispatch;
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci		/* Emit the vertex buffer age */
7608c2ecf20Sopenharmony_ci		BEGIN_RING(2);
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci		OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0));
7638c2ecf20Sopenharmony_ci		OUT_RING(buf_priv->age);
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci		ADVANCE_RING();
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci		buf->pending = 1;
7688c2ecf20Sopenharmony_ci		/* FIXME: Check dispatched field */
7698c2ecf20Sopenharmony_ci		buf_priv->dispatched = 0;
7708c2ecf20Sopenharmony_ci	}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci	dev_priv->sarea_priv->last_dispatch++;
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci	sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS;
7758c2ecf20Sopenharmony_ci	sarea_priv->nbox = 0;
7768c2ecf20Sopenharmony_ci}
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_cistatic int r128_cce_dispatch_blit(struct drm_device *dev,
7798c2ecf20Sopenharmony_ci				  struct drm_file *file_priv,
7808c2ecf20Sopenharmony_ci				  drm_r128_blit_t *blit)
7818c2ecf20Sopenharmony_ci{
7828c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
7838c2ecf20Sopenharmony_ci	struct drm_device_dma *dma = dev->dma;
7848c2ecf20Sopenharmony_ci	struct drm_buf *buf;
7858c2ecf20Sopenharmony_ci	drm_r128_buf_priv_t *buf_priv;
7868c2ecf20Sopenharmony_ci	u32 *data;
7878c2ecf20Sopenharmony_ci	int dword_shift, dwords;
7888c2ecf20Sopenharmony_ci	RING_LOCALS;
7898c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	/* The compiler won't optimize away a division by a variable,
7928c2ecf20Sopenharmony_ci	 * even if the only legal values are powers of two.  Thus, we'll
7938c2ecf20Sopenharmony_ci	 * use a shift instead.
7948c2ecf20Sopenharmony_ci	 */
7958c2ecf20Sopenharmony_ci	switch (blit->format) {
7968c2ecf20Sopenharmony_ci	case R128_DATATYPE_ARGB8888:
7978c2ecf20Sopenharmony_ci		dword_shift = 0;
7988c2ecf20Sopenharmony_ci		break;
7998c2ecf20Sopenharmony_ci	case R128_DATATYPE_ARGB1555:
8008c2ecf20Sopenharmony_ci	case R128_DATATYPE_RGB565:
8018c2ecf20Sopenharmony_ci	case R128_DATATYPE_ARGB4444:
8028c2ecf20Sopenharmony_ci	case R128_DATATYPE_YVYU422:
8038c2ecf20Sopenharmony_ci	case R128_DATATYPE_VYUY422:
8048c2ecf20Sopenharmony_ci		dword_shift = 1;
8058c2ecf20Sopenharmony_ci		break;
8068c2ecf20Sopenharmony_ci	case R128_DATATYPE_CI8:
8078c2ecf20Sopenharmony_ci	case R128_DATATYPE_RGB8:
8088c2ecf20Sopenharmony_ci		dword_shift = 2;
8098c2ecf20Sopenharmony_ci		break;
8108c2ecf20Sopenharmony_ci	default:
8118c2ecf20Sopenharmony_ci		DRM_ERROR("invalid blit format %d\n", blit->format);
8128c2ecf20Sopenharmony_ci		return -EINVAL;
8138c2ecf20Sopenharmony_ci	}
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	/* Flush the pixel cache, and mark the contents as Read Invalid.
8168c2ecf20Sopenharmony_ci	 * This ensures no pixel data gets mixed up with the texture
8178c2ecf20Sopenharmony_ci	 * data from the host data blit, otherwise part of the texture
8188c2ecf20Sopenharmony_ci	 * image may be corrupted.
8198c2ecf20Sopenharmony_ci	 */
8208c2ecf20Sopenharmony_ci	BEGIN_RING(2);
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
8238c2ecf20Sopenharmony_ci	OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI);
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	ADVANCE_RING();
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	/* Dispatch the indirect buffer.
8288c2ecf20Sopenharmony_ci	 */
8298c2ecf20Sopenharmony_ci	buf = dma->buflist[blit->idx];
8308c2ecf20Sopenharmony_ci	buf_priv = buf->dev_private;
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	if (buf->file_priv != file_priv) {
8338c2ecf20Sopenharmony_ci		DRM_ERROR("process %d using buffer owned by %p\n",
8348c2ecf20Sopenharmony_ci			  task_pid_nr(current), buf->file_priv);
8358c2ecf20Sopenharmony_ci		return -EINVAL;
8368c2ecf20Sopenharmony_ci	}
8378c2ecf20Sopenharmony_ci	if (buf->pending) {
8388c2ecf20Sopenharmony_ci		DRM_ERROR("sending pending buffer %d\n", blit->idx);
8398c2ecf20Sopenharmony_ci		return -EINVAL;
8408c2ecf20Sopenharmony_ci	}
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci	buf_priv->discard = 1;
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	dwords = (blit->width * blit->height) >> dword_shift;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset);
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6));
8498c2ecf20Sopenharmony_ci	data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL |
8508c2ecf20Sopenharmony_ci			       R128_GMC_BRUSH_NONE |
8518c2ecf20Sopenharmony_ci			       (blit->format << 8) |
8528c2ecf20Sopenharmony_ci			       R128_GMC_SRC_DATATYPE_COLOR |
8538c2ecf20Sopenharmony_ci			       R128_ROP3_S |
8548c2ecf20Sopenharmony_ci			       R128_DP_SRC_SOURCE_HOST_DATA |
8558c2ecf20Sopenharmony_ci			       R128_GMC_CLR_CMP_CNTL_DIS |
8568c2ecf20Sopenharmony_ci			       R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS));
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5));
8598c2ecf20Sopenharmony_ci	data[3] = cpu_to_le32(0xffffffff);
8608c2ecf20Sopenharmony_ci	data[4] = cpu_to_le32(0xffffffff);
8618c2ecf20Sopenharmony_ci	data[5] = cpu_to_le32((blit->y << 16) | blit->x);
8628c2ecf20Sopenharmony_ci	data[6] = cpu_to_le32((blit->height << 16) | blit->width);
8638c2ecf20Sopenharmony_ci	data[7] = cpu_to_le32(dwords);
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	buf->used = (dwords + 8) * sizeof(u32);
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	r128_cce_dispatch_indirect(dev, buf, 0, buf->used);
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	/* Flush the pixel cache after the blit completes.  This ensures
8708c2ecf20Sopenharmony_ci	 * the texture data is written out to memory before rendering
8718c2ecf20Sopenharmony_ci	 * continues.
8728c2ecf20Sopenharmony_ci	 */
8738c2ecf20Sopenharmony_ci	BEGIN_RING(2);
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0));
8768c2ecf20Sopenharmony_ci	OUT_RING(R128_PC_FLUSH_GUI);
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	ADVANCE_RING();
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	return 0;
8818c2ecf20Sopenharmony_ci}
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci/* ================================================================
8848c2ecf20Sopenharmony_ci * Tiled depth buffer management
8858c2ecf20Sopenharmony_ci *
8868c2ecf20Sopenharmony_ci * FIXME: These should all set the destination write mask for when we
8878c2ecf20Sopenharmony_ci * have hardware stencil support.
8888c2ecf20Sopenharmony_ci */
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_cistatic int r128_cce_dispatch_write_span(struct drm_device *dev,
8918c2ecf20Sopenharmony_ci					drm_r128_depth_t *depth)
8928c2ecf20Sopenharmony_ci{
8938c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
8948c2ecf20Sopenharmony_ci	int count, x, y;
8958c2ecf20Sopenharmony_ci	u32 *buffer;
8968c2ecf20Sopenharmony_ci	u8 *mask;
8978c2ecf20Sopenharmony_ci	int i, buffer_size, mask_size;
8988c2ecf20Sopenharmony_ci	RING_LOCALS;
8998c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	count = depth->n;
9028c2ecf20Sopenharmony_ci	if (count > 4096 || count <= 0)
9038c2ecf20Sopenharmony_ci		return -EMSGSIZE;
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci	if (copy_from_user(&x, depth->x, sizeof(x)))
9068c2ecf20Sopenharmony_ci		return -EFAULT;
9078c2ecf20Sopenharmony_ci	if (copy_from_user(&y, depth->y, sizeof(y)))
9088c2ecf20Sopenharmony_ci		return -EFAULT;
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	buffer_size = depth->n * sizeof(u32);
9118c2ecf20Sopenharmony_ci	buffer = memdup_user(depth->buffer, buffer_size);
9128c2ecf20Sopenharmony_ci	if (IS_ERR(buffer))
9138c2ecf20Sopenharmony_ci		return PTR_ERR(buffer);
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	mask_size = depth->n;
9168c2ecf20Sopenharmony_ci	if (depth->mask) {
9178c2ecf20Sopenharmony_ci		mask = memdup_user(depth->mask, mask_size);
9188c2ecf20Sopenharmony_ci		if (IS_ERR(mask)) {
9198c2ecf20Sopenharmony_ci			kfree(buffer);
9208c2ecf20Sopenharmony_ci			return PTR_ERR(mask);
9218c2ecf20Sopenharmony_ci		}
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci		for (i = 0; i < count; i++, x++) {
9248c2ecf20Sopenharmony_ci			if (mask[i]) {
9258c2ecf20Sopenharmony_ci				BEGIN_RING(6);
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci				OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
9288c2ecf20Sopenharmony_ci				OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
9298c2ecf20Sopenharmony_ci					 R128_GMC_BRUSH_SOLID_COLOR |
9308c2ecf20Sopenharmony_ci					 (dev_priv->depth_fmt << 8) |
9318c2ecf20Sopenharmony_ci					 R128_GMC_SRC_DATATYPE_COLOR |
9328c2ecf20Sopenharmony_ci					 R128_ROP3_P |
9338c2ecf20Sopenharmony_ci					 R128_GMC_CLR_CMP_CNTL_DIS |
9348c2ecf20Sopenharmony_ci					 R128_GMC_WR_MSK_DIS);
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_ci				OUT_RING(dev_priv->depth_pitch_offset_c);
9378c2ecf20Sopenharmony_ci				OUT_RING(buffer[i]);
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci				OUT_RING((x << 16) | y);
9408c2ecf20Sopenharmony_ci				OUT_RING((1 << 16) | 1);
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci				ADVANCE_RING();
9438c2ecf20Sopenharmony_ci			}
9448c2ecf20Sopenharmony_ci		}
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci		kfree(mask);
9478c2ecf20Sopenharmony_ci	} else {
9488c2ecf20Sopenharmony_ci		for (i = 0; i < count; i++, x++) {
9498c2ecf20Sopenharmony_ci			BEGIN_RING(6);
9508c2ecf20Sopenharmony_ci
9518c2ecf20Sopenharmony_ci			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
9528c2ecf20Sopenharmony_ci			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
9538c2ecf20Sopenharmony_ci				 R128_GMC_BRUSH_SOLID_COLOR |
9548c2ecf20Sopenharmony_ci				 (dev_priv->depth_fmt << 8) |
9558c2ecf20Sopenharmony_ci				 R128_GMC_SRC_DATATYPE_COLOR |
9568c2ecf20Sopenharmony_ci				 R128_ROP3_P |
9578c2ecf20Sopenharmony_ci				 R128_GMC_CLR_CMP_CNTL_DIS |
9588c2ecf20Sopenharmony_ci				 R128_GMC_WR_MSK_DIS);
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci			OUT_RING(dev_priv->depth_pitch_offset_c);
9618c2ecf20Sopenharmony_ci			OUT_RING(buffer[i]);
9628c2ecf20Sopenharmony_ci
9638c2ecf20Sopenharmony_ci			OUT_RING((x << 16) | y);
9648c2ecf20Sopenharmony_ci			OUT_RING((1 << 16) | 1);
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci			ADVANCE_RING();
9678c2ecf20Sopenharmony_ci		}
9688c2ecf20Sopenharmony_ci	}
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	kfree(buffer);
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	return 0;
9738c2ecf20Sopenharmony_ci}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_cistatic int r128_cce_dispatch_write_pixels(struct drm_device *dev,
9768c2ecf20Sopenharmony_ci					  drm_r128_depth_t *depth)
9778c2ecf20Sopenharmony_ci{
9788c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
9798c2ecf20Sopenharmony_ci	int count, *x, *y;
9808c2ecf20Sopenharmony_ci	u32 *buffer;
9818c2ecf20Sopenharmony_ci	u8 *mask;
9828c2ecf20Sopenharmony_ci	int i, xbuf_size, ybuf_size, buffer_size, mask_size;
9838c2ecf20Sopenharmony_ci	RING_LOCALS;
9848c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci	count = depth->n;
9878c2ecf20Sopenharmony_ci	if (count > 4096 || count <= 0)
9888c2ecf20Sopenharmony_ci		return -EMSGSIZE;
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	xbuf_size = count * sizeof(*x);
9918c2ecf20Sopenharmony_ci	ybuf_size = count * sizeof(*y);
9928c2ecf20Sopenharmony_ci	x = memdup_user(depth->x, xbuf_size);
9938c2ecf20Sopenharmony_ci	if (IS_ERR(x))
9948c2ecf20Sopenharmony_ci		return PTR_ERR(x);
9958c2ecf20Sopenharmony_ci	y = memdup_user(depth->y, ybuf_size);
9968c2ecf20Sopenharmony_ci	if (IS_ERR(y)) {
9978c2ecf20Sopenharmony_ci		kfree(x);
9988c2ecf20Sopenharmony_ci		return PTR_ERR(y);
9998c2ecf20Sopenharmony_ci	}
10008c2ecf20Sopenharmony_ci	buffer_size = depth->n * sizeof(u32);
10018c2ecf20Sopenharmony_ci	buffer = memdup_user(depth->buffer, buffer_size);
10028c2ecf20Sopenharmony_ci	if (IS_ERR(buffer)) {
10038c2ecf20Sopenharmony_ci		kfree(x);
10048c2ecf20Sopenharmony_ci		kfree(y);
10058c2ecf20Sopenharmony_ci		return PTR_ERR(buffer);
10068c2ecf20Sopenharmony_ci	}
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	if (depth->mask) {
10098c2ecf20Sopenharmony_ci		mask_size = depth->n;
10108c2ecf20Sopenharmony_ci		mask = memdup_user(depth->mask, mask_size);
10118c2ecf20Sopenharmony_ci		if (IS_ERR(mask)) {
10128c2ecf20Sopenharmony_ci			kfree(x);
10138c2ecf20Sopenharmony_ci			kfree(y);
10148c2ecf20Sopenharmony_ci			kfree(buffer);
10158c2ecf20Sopenharmony_ci			return PTR_ERR(mask);
10168c2ecf20Sopenharmony_ci		}
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci		for (i = 0; i < count; i++) {
10198c2ecf20Sopenharmony_ci			if (mask[i]) {
10208c2ecf20Sopenharmony_ci				BEGIN_RING(6);
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci				OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
10238c2ecf20Sopenharmony_ci				OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
10248c2ecf20Sopenharmony_ci					 R128_GMC_BRUSH_SOLID_COLOR |
10258c2ecf20Sopenharmony_ci					 (dev_priv->depth_fmt << 8) |
10268c2ecf20Sopenharmony_ci					 R128_GMC_SRC_DATATYPE_COLOR |
10278c2ecf20Sopenharmony_ci					 R128_ROP3_P |
10288c2ecf20Sopenharmony_ci					 R128_GMC_CLR_CMP_CNTL_DIS |
10298c2ecf20Sopenharmony_ci					 R128_GMC_WR_MSK_DIS);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci				OUT_RING(dev_priv->depth_pitch_offset_c);
10328c2ecf20Sopenharmony_ci				OUT_RING(buffer[i]);
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci				OUT_RING((x[i] << 16) | y[i]);
10358c2ecf20Sopenharmony_ci				OUT_RING((1 << 16) | 1);
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci				ADVANCE_RING();
10388c2ecf20Sopenharmony_ci			}
10398c2ecf20Sopenharmony_ci		}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci		kfree(mask);
10428c2ecf20Sopenharmony_ci	} else {
10438c2ecf20Sopenharmony_ci		for (i = 0; i < count; i++) {
10448c2ecf20Sopenharmony_ci			BEGIN_RING(6);
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci			OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4));
10478c2ecf20Sopenharmony_ci			OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL |
10488c2ecf20Sopenharmony_ci				 R128_GMC_BRUSH_SOLID_COLOR |
10498c2ecf20Sopenharmony_ci				 (dev_priv->depth_fmt << 8) |
10508c2ecf20Sopenharmony_ci				 R128_GMC_SRC_DATATYPE_COLOR |
10518c2ecf20Sopenharmony_ci				 R128_ROP3_P |
10528c2ecf20Sopenharmony_ci				 R128_GMC_CLR_CMP_CNTL_DIS |
10538c2ecf20Sopenharmony_ci				 R128_GMC_WR_MSK_DIS);
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci			OUT_RING(dev_priv->depth_pitch_offset_c);
10568c2ecf20Sopenharmony_ci			OUT_RING(buffer[i]);
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci			OUT_RING((x[i] << 16) | y[i]);
10598c2ecf20Sopenharmony_ci			OUT_RING((1 << 16) | 1);
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci			ADVANCE_RING();
10628c2ecf20Sopenharmony_ci		}
10638c2ecf20Sopenharmony_ci	}
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci	kfree(x);
10668c2ecf20Sopenharmony_ci	kfree(y);
10678c2ecf20Sopenharmony_ci	kfree(buffer);
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci	return 0;
10708c2ecf20Sopenharmony_ci}
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_cistatic int r128_cce_dispatch_read_span(struct drm_device *dev,
10738c2ecf20Sopenharmony_ci				       drm_r128_depth_t *depth)
10748c2ecf20Sopenharmony_ci{
10758c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
10768c2ecf20Sopenharmony_ci	int count, x, y;
10778c2ecf20Sopenharmony_ci	RING_LOCALS;
10788c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	count = depth->n;
10818c2ecf20Sopenharmony_ci	if (count > 4096 || count <= 0)
10828c2ecf20Sopenharmony_ci		return -EMSGSIZE;
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	if (copy_from_user(&x, depth->x, sizeof(x)))
10858c2ecf20Sopenharmony_ci		return -EFAULT;
10868c2ecf20Sopenharmony_ci	if (copy_from_user(&y, depth->y, sizeof(y)))
10878c2ecf20Sopenharmony_ci		return -EFAULT;
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	BEGIN_RING(7);
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
10928c2ecf20Sopenharmony_ci	OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
10938c2ecf20Sopenharmony_ci		 R128_GMC_DST_PITCH_OFFSET_CNTL |
10948c2ecf20Sopenharmony_ci		 R128_GMC_BRUSH_NONE |
10958c2ecf20Sopenharmony_ci		 (dev_priv->depth_fmt << 8) |
10968c2ecf20Sopenharmony_ci		 R128_GMC_SRC_DATATYPE_COLOR |
10978c2ecf20Sopenharmony_ci		 R128_ROP3_S |
10988c2ecf20Sopenharmony_ci		 R128_DP_SRC_SOURCE_MEMORY |
10998c2ecf20Sopenharmony_ci		 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	OUT_RING(dev_priv->depth_pitch_offset_c);
11028c2ecf20Sopenharmony_ci	OUT_RING(dev_priv->span_pitch_offset_c);
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	OUT_RING((x << 16) | y);
11058c2ecf20Sopenharmony_ci	OUT_RING((0 << 16) | 0);
11068c2ecf20Sopenharmony_ci	OUT_RING((count << 16) | 1);
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci	ADVANCE_RING();
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	return 0;
11118c2ecf20Sopenharmony_ci}
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_cistatic int r128_cce_dispatch_read_pixels(struct drm_device *dev,
11148c2ecf20Sopenharmony_ci					 drm_r128_depth_t *depth)
11158c2ecf20Sopenharmony_ci{
11168c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
11178c2ecf20Sopenharmony_ci	int count, *x, *y;
11188c2ecf20Sopenharmony_ci	int i, xbuf_size, ybuf_size;
11198c2ecf20Sopenharmony_ci	RING_LOCALS;
11208c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	count = depth->n;
11238c2ecf20Sopenharmony_ci	if (count > 4096 || count <= 0)
11248c2ecf20Sopenharmony_ci		return -EMSGSIZE;
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	if (count > dev_priv->depth_pitch)
11278c2ecf20Sopenharmony_ci		count = dev_priv->depth_pitch;
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci	xbuf_size = count * sizeof(*x);
11308c2ecf20Sopenharmony_ci	ybuf_size = count * sizeof(*y);
11318c2ecf20Sopenharmony_ci	x = kmalloc(xbuf_size, GFP_KERNEL);
11328c2ecf20Sopenharmony_ci	if (x == NULL)
11338c2ecf20Sopenharmony_ci		return -ENOMEM;
11348c2ecf20Sopenharmony_ci	y = kmalloc(ybuf_size, GFP_KERNEL);
11358c2ecf20Sopenharmony_ci	if (y == NULL) {
11368c2ecf20Sopenharmony_ci		kfree(x);
11378c2ecf20Sopenharmony_ci		return -ENOMEM;
11388c2ecf20Sopenharmony_ci	}
11398c2ecf20Sopenharmony_ci	if (copy_from_user(x, depth->x, xbuf_size)) {
11408c2ecf20Sopenharmony_ci		kfree(x);
11418c2ecf20Sopenharmony_ci		kfree(y);
11428c2ecf20Sopenharmony_ci		return -EFAULT;
11438c2ecf20Sopenharmony_ci	}
11448c2ecf20Sopenharmony_ci	if (copy_from_user(y, depth->y, ybuf_size)) {
11458c2ecf20Sopenharmony_ci		kfree(x);
11468c2ecf20Sopenharmony_ci		kfree(y);
11478c2ecf20Sopenharmony_ci		return -EFAULT;
11488c2ecf20Sopenharmony_ci	}
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++) {
11518c2ecf20Sopenharmony_ci		BEGIN_RING(7);
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci		OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5));
11548c2ecf20Sopenharmony_ci		OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL |
11558c2ecf20Sopenharmony_ci			 R128_GMC_DST_PITCH_OFFSET_CNTL |
11568c2ecf20Sopenharmony_ci			 R128_GMC_BRUSH_NONE |
11578c2ecf20Sopenharmony_ci			 (dev_priv->depth_fmt << 8) |
11588c2ecf20Sopenharmony_ci			 R128_GMC_SRC_DATATYPE_COLOR |
11598c2ecf20Sopenharmony_ci			 R128_ROP3_S |
11608c2ecf20Sopenharmony_ci			 R128_DP_SRC_SOURCE_MEMORY |
11618c2ecf20Sopenharmony_ci			 R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS);
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci		OUT_RING(dev_priv->depth_pitch_offset_c);
11648c2ecf20Sopenharmony_ci		OUT_RING(dev_priv->span_pitch_offset_c);
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci		OUT_RING((x[i] << 16) | y[i]);
11678c2ecf20Sopenharmony_ci		OUT_RING((i << 16) | 0);
11688c2ecf20Sopenharmony_ci		OUT_RING((1 << 16) | 1);
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci		ADVANCE_RING();
11718c2ecf20Sopenharmony_ci	}
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ci	kfree(x);
11748c2ecf20Sopenharmony_ci	kfree(y);
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	return 0;
11778c2ecf20Sopenharmony_ci}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci/* ================================================================
11808c2ecf20Sopenharmony_ci * Polygon stipple
11818c2ecf20Sopenharmony_ci */
11828c2ecf20Sopenharmony_ci
11838c2ecf20Sopenharmony_cistatic void r128_cce_dispatch_stipple(struct drm_device *dev, u32 *stipple)
11848c2ecf20Sopenharmony_ci{
11858c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
11868c2ecf20Sopenharmony_ci	int i;
11878c2ecf20Sopenharmony_ci	RING_LOCALS;
11888c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	BEGIN_RING(33);
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31));
11938c2ecf20Sopenharmony_ci	for (i = 0; i < 32; i++)
11948c2ecf20Sopenharmony_ci		OUT_RING(stipple[i]);
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	ADVANCE_RING();
11978c2ecf20Sopenharmony_ci}
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci/* ================================================================
12008c2ecf20Sopenharmony_ci * IOCTL functions
12018c2ecf20Sopenharmony_ci */
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_cistatic int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
12048c2ecf20Sopenharmony_ci{
12058c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
12068c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv;
12078c2ecf20Sopenharmony_ci	drm_r128_clear_t *clear = data;
12088c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci	LOCK_TEST_WITH_RETURN(dev, file_priv);
12118c2ecf20Sopenharmony_ci
12128c2ecf20Sopenharmony_ci	DEV_INIT_TEST_WITH_RETURN(dev_priv);
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	RING_SPACE_TEST_WITH_RETURN(dev_priv);
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	sarea_priv = dev_priv->sarea_priv;
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_ci	if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
12198c2ecf20Sopenharmony_ci		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci	r128_cce_dispatch_clear(dev, clear);
12228c2ecf20Sopenharmony_ci	COMMIT_RING();
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci	/* Make sure we restore the 3D state next time.
12258c2ecf20Sopenharmony_ci	 */
12268c2ecf20Sopenharmony_ci	dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	return 0;
12298c2ecf20Sopenharmony_ci}
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_cistatic int r128_do_init_pageflip(struct drm_device *dev)
12328c2ecf20Sopenharmony_ci{
12338c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
12348c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET);
12378c2ecf20Sopenharmony_ci	dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL);
12388c2ecf20Sopenharmony_ci
12398c2ecf20Sopenharmony_ci	R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset);
12408c2ecf20Sopenharmony_ci	R128_WRITE(R128_CRTC_OFFSET_CNTL,
12418c2ecf20Sopenharmony_ci		   dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL);
12428c2ecf20Sopenharmony_ci
12438c2ecf20Sopenharmony_ci	dev_priv->page_flipping = 1;
12448c2ecf20Sopenharmony_ci	dev_priv->current_page = 0;
12458c2ecf20Sopenharmony_ci	dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page;
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	return 0;
12488c2ecf20Sopenharmony_ci}
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_cistatic int r128_do_cleanup_pageflip(struct drm_device *dev)
12518c2ecf20Sopenharmony_ci{
12528c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
12538c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset);
12568c2ecf20Sopenharmony_ci	R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl);
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	if (dev_priv->current_page != 0) {
12598c2ecf20Sopenharmony_ci		r128_cce_dispatch_flip(dev);
12608c2ecf20Sopenharmony_ci		COMMIT_RING();
12618c2ecf20Sopenharmony_ci	}
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	dev_priv->page_flipping = 0;
12648c2ecf20Sopenharmony_ci	return 0;
12658c2ecf20Sopenharmony_ci}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci/* Swapping and flipping are different operations, need different ioctls.
12688c2ecf20Sopenharmony_ci * They can & should be intermixed to support multiple 3d windows.
12698c2ecf20Sopenharmony_ci */
12708c2ecf20Sopenharmony_ci
12718c2ecf20Sopenharmony_cistatic int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv)
12728c2ecf20Sopenharmony_ci{
12738c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
12748c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_ci	LOCK_TEST_WITH_RETURN(dev, file_priv);
12778c2ecf20Sopenharmony_ci
12788c2ecf20Sopenharmony_ci	DEV_INIT_TEST_WITH_RETURN(dev_priv);
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	RING_SPACE_TEST_WITH_RETURN(dev_priv);
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	if (!dev_priv->page_flipping)
12838c2ecf20Sopenharmony_ci		r128_do_init_pageflip(dev);
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	r128_cce_dispatch_flip(dev);
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	COMMIT_RING();
12888c2ecf20Sopenharmony_ci	return 0;
12898c2ecf20Sopenharmony_ci}
12908c2ecf20Sopenharmony_ci
12918c2ecf20Sopenharmony_cistatic int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
12928c2ecf20Sopenharmony_ci{
12938c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
12948c2ecf20Sopenharmony_ci	drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv;
12958c2ecf20Sopenharmony_ci	DRM_DEBUG("\n");
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	LOCK_TEST_WITH_RETURN(dev, file_priv);
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	DEV_INIT_TEST_WITH_RETURN(dev_priv);
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_ci	RING_SPACE_TEST_WITH_RETURN(dev_priv);
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
13048c2ecf20Sopenharmony_ci		sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
13058c2ecf20Sopenharmony_ci
13068c2ecf20Sopenharmony_ci	r128_cce_dispatch_swap(dev);
13078c2ecf20Sopenharmony_ci	dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT |
13088c2ecf20Sopenharmony_ci					R128_UPLOAD_MASKS);
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci	COMMIT_RING();
13118c2ecf20Sopenharmony_ci	return 0;
13128c2ecf20Sopenharmony_ci}
13138c2ecf20Sopenharmony_ci
13148c2ecf20Sopenharmony_cistatic int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
13158c2ecf20Sopenharmony_ci{
13168c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
13178c2ecf20Sopenharmony_ci	struct drm_device_dma *dma = dev->dma;
13188c2ecf20Sopenharmony_ci	struct drm_buf *buf;
13198c2ecf20Sopenharmony_ci	drm_r128_buf_priv_t *buf_priv;
13208c2ecf20Sopenharmony_ci	drm_r128_vertex_t *vertex = data;
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	LOCK_TEST_WITH_RETURN(dev, file_priv);
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_ci	DEV_INIT_TEST_WITH_RETURN(dev_priv);
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ci	DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
13278c2ecf20Sopenharmony_ci		  task_pid_nr(current), vertex->idx, vertex->count, vertex->discard);
13288c2ecf20Sopenharmony_ci
13298c2ecf20Sopenharmony_ci	if (vertex->idx < 0 || vertex->idx >= dma->buf_count) {
13308c2ecf20Sopenharmony_ci		DRM_ERROR("buffer index %d (of %d max)\n",
13318c2ecf20Sopenharmony_ci			  vertex->idx, dma->buf_count - 1);
13328c2ecf20Sopenharmony_ci		return -EINVAL;
13338c2ecf20Sopenharmony_ci	}
13348c2ecf20Sopenharmony_ci	if (vertex->prim < 0 ||
13358c2ecf20Sopenharmony_ci	    vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
13368c2ecf20Sopenharmony_ci		DRM_ERROR("buffer prim %d\n", vertex->prim);
13378c2ecf20Sopenharmony_ci		return -EINVAL;
13388c2ecf20Sopenharmony_ci	}
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	RING_SPACE_TEST_WITH_RETURN(dev_priv);
13418c2ecf20Sopenharmony_ci	VB_AGE_TEST_WITH_RETURN(dev_priv);
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	buf = dma->buflist[vertex->idx];
13448c2ecf20Sopenharmony_ci	buf_priv = buf->dev_private;
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ci	if (buf->file_priv != file_priv) {
13478c2ecf20Sopenharmony_ci		DRM_ERROR("process %d using buffer owned by %p\n",
13488c2ecf20Sopenharmony_ci			  task_pid_nr(current), buf->file_priv);
13498c2ecf20Sopenharmony_ci		return -EINVAL;
13508c2ecf20Sopenharmony_ci	}
13518c2ecf20Sopenharmony_ci	if (buf->pending) {
13528c2ecf20Sopenharmony_ci		DRM_ERROR("sending pending buffer %d\n", vertex->idx);
13538c2ecf20Sopenharmony_ci		return -EINVAL;
13548c2ecf20Sopenharmony_ci	}
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	buf->used = vertex->count;
13578c2ecf20Sopenharmony_ci	buf_priv->prim = vertex->prim;
13588c2ecf20Sopenharmony_ci	buf_priv->discard = vertex->discard;
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci	r128_cce_dispatch_vertex(dev, buf);
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci	COMMIT_RING();
13638c2ecf20Sopenharmony_ci	return 0;
13648c2ecf20Sopenharmony_ci}
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_cistatic int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
13678c2ecf20Sopenharmony_ci{
13688c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
13698c2ecf20Sopenharmony_ci	struct drm_device_dma *dma = dev->dma;
13708c2ecf20Sopenharmony_ci	struct drm_buf *buf;
13718c2ecf20Sopenharmony_ci	drm_r128_buf_priv_t *buf_priv;
13728c2ecf20Sopenharmony_ci	drm_r128_indices_t *elts = data;
13738c2ecf20Sopenharmony_ci	int count;
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	LOCK_TEST_WITH_RETURN(dev, file_priv);
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci	DEV_INIT_TEST_WITH_RETURN(dev_priv);
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", task_pid_nr(current),
13808c2ecf20Sopenharmony_ci		  elts->idx, elts->start, elts->end, elts->discard);
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_ci	if (elts->idx < 0 || elts->idx >= dma->buf_count) {
13838c2ecf20Sopenharmony_ci		DRM_ERROR("buffer index %d (of %d max)\n",
13848c2ecf20Sopenharmony_ci			  elts->idx, dma->buf_count - 1);
13858c2ecf20Sopenharmony_ci		return -EINVAL;
13868c2ecf20Sopenharmony_ci	}
13878c2ecf20Sopenharmony_ci	if (elts->prim < 0 ||
13888c2ecf20Sopenharmony_ci	    elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) {
13898c2ecf20Sopenharmony_ci		DRM_ERROR("buffer prim %d\n", elts->prim);
13908c2ecf20Sopenharmony_ci		return -EINVAL;
13918c2ecf20Sopenharmony_ci	}
13928c2ecf20Sopenharmony_ci
13938c2ecf20Sopenharmony_ci	RING_SPACE_TEST_WITH_RETURN(dev_priv);
13948c2ecf20Sopenharmony_ci	VB_AGE_TEST_WITH_RETURN(dev_priv);
13958c2ecf20Sopenharmony_ci
13968c2ecf20Sopenharmony_ci	buf = dma->buflist[elts->idx];
13978c2ecf20Sopenharmony_ci	buf_priv = buf->dev_private;
13988c2ecf20Sopenharmony_ci
13998c2ecf20Sopenharmony_ci	if (buf->file_priv != file_priv) {
14008c2ecf20Sopenharmony_ci		DRM_ERROR("process %d using buffer owned by %p\n",
14018c2ecf20Sopenharmony_ci			  task_pid_nr(current), buf->file_priv);
14028c2ecf20Sopenharmony_ci		return -EINVAL;
14038c2ecf20Sopenharmony_ci	}
14048c2ecf20Sopenharmony_ci	if (buf->pending) {
14058c2ecf20Sopenharmony_ci		DRM_ERROR("sending pending buffer %d\n", elts->idx);
14068c2ecf20Sopenharmony_ci		return -EINVAL;
14078c2ecf20Sopenharmony_ci	}
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci	count = (elts->end - elts->start) / sizeof(u16);
14108c2ecf20Sopenharmony_ci	elts->start -= R128_INDEX_PRIM_OFFSET;
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_ci	if (elts->start & 0x7) {
14138c2ecf20Sopenharmony_ci		DRM_ERROR("misaligned buffer 0x%x\n", elts->start);
14148c2ecf20Sopenharmony_ci		return -EINVAL;
14158c2ecf20Sopenharmony_ci	}
14168c2ecf20Sopenharmony_ci	if (elts->start < buf->used) {
14178c2ecf20Sopenharmony_ci		DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used);
14188c2ecf20Sopenharmony_ci		return -EINVAL;
14198c2ecf20Sopenharmony_ci	}
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	buf->used = elts->end;
14228c2ecf20Sopenharmony_ci	buf_priv->prim = elts->prim;
14238c2ecf20Sopenharmony_ci	buf_priv->discard = elts->discard;
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count);
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci	COMMIT_RING();
14288c2ecf20Sopenharmony_ci	return 0;
14298c2ecf20Sopenharmony_ci}
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_cistatic int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv)
14328c2ecf20Sopenharmony_ci{
14338c2ecf20Sopenharmony_ci	struct drm_device_dma *dma = dev->dma;
14348c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
14358c2ecf20Sopenharmony_ci	drm_r128_blit_t *blit = data;
14368c2ecf20Sopenharmony_ci	int ret;
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci	LOCK_TEST_WITH_RETURN(dev, file_priv);
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci	DEV_INIT_TEST_WITH_RETURN(dev_priv);
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	DRM_DEBUG("pid=%d index=%d\n", task_pid_nr(current), blit->idx);
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	if (blit->idx < 0 || blit->idx >= dma->buf_count) {
14458c2ecf20Sopenharmony_ci		DRM_ERROR("buffer index %d (of %d max)\n",
14468c2ecf20Sopenharmony_ci			  blit->idx, dma->buf_count - 1);
14478c2ecf20Sopenharmony_ci		return -EINVAL;
14488c2ecf20Sopenharmony_ci	}
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	RING_SPACE_TEST_WITH_RETURN(dev_priv);
14518c2ecf20Sopenharmony_ci	VB_AGE_TEST_WITH_RETURN(dev_priv);
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	ret = r128_cce_dispatch_blit(dev, file_priv, blit);
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci	COMMIT_RING();
14568c2ecf20Sopenharmony_ci	return ret;
14578c2ecf20Sopenharmony_ci}
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ciint r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv)
14608c2ecf20Sopenharmony_ci{
14618c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
14628c2ecf20Sopenharmony_ci	drm_r128_depth_t *depth = data;
14638c2ecf20Sopenharmony_ci	int ret;
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci	LOCK_TEST_WITH_RETURN(dev, file_priv);
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci	DEV_INIT_TEST_WITH_RETURN(dev_priv);
14688c2ecf20Sopenharmony_ci
14698c2ecf20Sopenharmony_ci	RING_SPACE_TEST_WITH_RETURN(dev_priv);
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_ci	ret = -EINVAL;
14728c2ecf20Sopenharmony_ci	switch (depth->func) {
14738c2ecf20Sopenharmony_ci	case R128_WRITE_SPAN:
14748c2ecf20Sopenharmony_ci		ret = r128_cce_dispatch_write_span(dev, depth);
14758c2ecf20Sopenharmony_ci		break;
14768c2ecf20Sopenharmony_ci	case R128_WRITE_PIXELS:
14778c2ecf20Sopenharmony_ci		ret = r128_cce_dispatch_write_pixels(dev, depth);
14788c2ecf20Sopenharmony_ci		break;
14798c2ecf20Sopenharmony_ci	case R128_READ_SPAN:
14808c2ecf20Sopenharmony_ci		ret = r128_cce_dispatch_read_span(dev, depth);
14818c2ecf20Sopenharmony_ci		break;
14828c2ecf20Sopenharmony_ci	case R128_READ_PIXELS:
14838c2ecf20Sopenharmony_ci		ret = r128_cce_dispatch_read_pixels(dev, depth);
14848c2ecf20Sopenharmony_ci		break;
14858c2ecf20Sopenharmony_ci	}
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	COMMIT_RING();
14888c2ecf20Sopenharmony_ci	return ret;
14898c2ecf20Sopenharmony_ci}
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ciint r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv)
14928c2ecf20Sopenharmony_ci{
14938c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
14948c2ecf20Sopenharmony_ci	drm_r128_stipple_t *stipple = data;
14958c2ecf20Sopenharmony_ci	u32 mask[32];
14968c2ecf20Sopenharmony_ci
14978c2ecf20Sopenharmony_ci	LOCK_TEST_WITH_RETURN(dev, file_priv);
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci	DEV_INIT_TEST_WITH_RETURN(dev_priv);
15008c2ecf20Sopenharmony_ci
15018c2ecf20Sopenharmony_ci	if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32)))
15028c2ecf20Sopenharmony_ci		return -EFAULT;
15038c2ecf20Sopenharmony_ci
15048c2ecf20Sopenharmony_ci	RING_SPACE_TEST_WITH_RETURN(dev_priv);
15058c2ecf20Sopenharmony_ci
15068c2ecf20Sopenharmony_ci	r128_cce_dispatch_stipple(dev, mask);
15078c2ecf20Sopenharmony_ci
15088c2ecf20Sopenharmony_ci	COMMIT_RING();
15098c2ecf20Sopenharmony_ci	return 0;
15108c2ecf20Sopenharmony_ci}
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_cistatic int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv)
15138c2ecf20Sopenharmony_ci{
15148c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
15158c2ecf20Sopenharmony_ci	struct drm_device_dma *dma = dev->dma;
15168c2ecf20Sopenharmony_ci	struct drm_buf *buf;
15178c2ecf20Sopenharmony_ci	drm_r128_buf_priv_t *buf_priv;
15188c2ecf20Sopenharmony_ci	drm_r128_indirect_t *indirect = data;
15198c2ecf20Sopenharmony_ci#if 0
15208c2ecf20Sopenharmony_ci	RING_LOCALS;
15218c2ecf20Sopenharmony_ci#endif
15228c2ecf20Sopenharmony_ci
15238c2ecf20Sopenharmony_ci	LOCK_TEST_WITH_RETURN(dev, file_priv);
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_ci	DEV_INIT_TEST_WITH_RETURN(dev_priv);
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_ci	DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
15288c2ecf20Sopenharmony_ci		  indirect->idx, indirect->start, indirect->end,
15298c2ecf20Sopenharmony_ci		  indirect->discard);
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	if (indirect->idx < 0 || indirect->idx >= dma->buf_count) {
15328c2ecf20Sopenharmony_ci		DRM_ERROR("buffer index %d (of %d max)\n",
15338c2ecf20Sopenharmony_ci			  indirect->idx, dma->buf_count - 1);
15348c2ecf20Sopenharmony_ci		return -EINVAL;
15358c2ecf20Sopenharmony_ci	}
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci	buf = dma->buflist[indirect->idx];
15388c2ecf20Sopenharmony_ci	buf_priv = buf->dev_private;
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	if (buf->file_priv != file_priv) {
15418c2ecf20Sopenharmony_ci		DRM_ERROR("process %d using buffer owned by %p\n",
15428c2ecf20Sopenharmony_ci			  task_pid_nr(current), buf->file_priv);
15438c2ecf20Sopenharmony_ci		return -EINVAL;
15448c2ecf20Sopenharmony_ci	}
15458c2ecf20Sopenharmony_ci	if (buf->pending) {
15468c2ecf20Sopenharmony_ci		DRM_ERROR("sending pending buffer %d\n", indirect->idx);
15478c2ecf20Sopenharmony_ci		return -EINVAL;
15488c2ecf20Sopenharmony_ci	}
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci	if (indirect->start < buf->used) {
15518c2ecf20Sopenharmony_ci		DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n",
15528c2ecf20Sopenharmony_ci			  indirect->start, buf->used);
15538c2ecf20Sopenharmony_ci		return -EINVAL;
15548c2ecf20Sopenharmony_ci	}
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_ci	RING_SPACE_TEST_WITH_RETURN(dev_priv);
15578c2ecf20Sopenharmony_ci	VB_AGE_TEST_WITH_RETURN(dev_priv);
15588c2ecf20Sopenharmony_ci
15598c2ecf20Sopenharmony_ci	buf->used = indirect->end;
15608c2ecf20Sopenharmony_ci	buf_priv->discard = indirect->discard;
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci#if 0
15638c2ecf20Sopenharmony_ci	/* Wait for the 3D stream to idle before the indirect buffer
15648c2ecf20Sopenharmony_ci	 * containing 2D acceleration commands is processed.
15658c2ecf20Sopenharmony_ci	 */
15668c2ecf20Sopenharmony_ci	BEGIN_RING(2);
15678c2ecf20Sopenharmony_ci	RADEON_WAIT_UNTIL_3D_IDLE();
15688c2ecf20Sopenharmony_ci	ADVANCE_RING();
15698c2ecf20Sopenharmony_ci#endif
15708c2ecf20Sopenharmony_ci
15718c2ecf20Sopenharmony_ci	/* Dispatch the indirect buffer full of commands from the
15728c2ecf20Sopenharmony_ci	 * X server.  This is insecure and is thus only available to
15738c2ecf20Sopenharmony_ci	 * privileged clients.
15748c2ecf20Sopenharmony_ci	 */
15758c2ecf20Sopenharmony_ci	r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end);
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_ci	COMMIT_RING();
15788c2ecf20Sopenharmony_ci	return 0;
15798c2ecf20Sopenharmony_ci}
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ciint r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
15828c2ecf20Sopenharmony_ci{
15838c2ecf20Sopenharmony_ci	drm_r128_private_t *dev_priv = dev->dev_private;
15848c2ecf20Sopenharmony_ci	drm_r128_getparam_t *param = data;
15858c2ecf20Sopenharmony_ci	int value;
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	DEV_INIT_TEST_WITH_RETURN(dev_priv);
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	DRM_DEBUG("pid=%d\n", task_pid_nr(current));
15908c2ecf20Sopenharmony_ci
15918c2ecf20Sopenharmony_ci	switch (param->param) {
15928c2ecf20Sopenharmony_ci	case R128_PARAM_IRQ_NR:
15938c2ecf20Sopenharmony_ci		value = dev->pdev->irq;
15948c2ecf20Sopenharmony_ci		break;
15958c2ecf20Sopenharmony_ci	default:
15968c2ecf20Sopenharmony_ci		return -EINVAL;
15978c2ecf20Sopenharmony_ci	}
15988c2ecf20Sopenharmony_ci
15998c2ecf20Sopenharmony_ci	if (copy_to_user(param->value, &value, sizeof(int))) {
16008c2ecf20Sopenharmony_ci		DRM_ERROR("copy_to_user\n");
16018c2ecf20Sopenharmony_ci		return -EFAULT;
16028c2ecf20Sopenharmony_ci	}
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci	return 0;
16058c2ecf20Sopenharmony_ci}
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_civoid r128_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
16088c2ecf20Sopenharmony_ci{
16098c2ecf20Sopenharmony_ci	if (dev->dev_private) {
16108c2ecf20Sopenharmony_ci		drm_r128_private_t *dev_priv = dev->dev_private;
16118c2ecf20Sopenharmony_ci		if (dev_priv->page_flipping)
16128c2ecf20Sopenharmony_ci			r128_do_cleanup_pageflip(dev);
16138c2ecf20Sopenharmony_ci	}
16148c2ecf20Sopenharmony_ci}
16158c2ecf20Sopenharmony_civoid r128_driver_lastclose(struct drm_device *dev)
16168c2ecf20Sopenharmony_ci{
16178c2ecf20Sopenharmony_ci	r128_do_cleanup_cce(dev);
16188c2ecf20Sopenharmony_ci}
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_ciconst struct drm_ioctl_desc r128_ioctls[] = {
16218c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
16228c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
16238c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
16248c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
16258c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_CCE_IDLE, r128_cce_idle, DRM_AUTH),
16268c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_RESET, r128_engine_reset, DRM_AUTH),
16278c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_FULLSCREEN, r128_fullscreen, DRM_AUTH),
16288c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_SWAP, r128_cce_swap, DRM_AUTH),
16298c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_FLIP, r128_cce_flip, DRM_AUTH),
16308c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_CLEAR, r128_cce_clear, DRM_AUTH),
16318c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_VERTEX, r128_cce_vertex, DRM_AUTH),
16328c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_INDICES, r128_cce_indices, DRM_AUTH),
16338c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_BLIT, r128_cce_blit, DRM_AUTH),
16348c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_DEPTH, r128_cce_depth, DRM_AUTH),
16358c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_STIPPLE, r128_cce_stipple, DRM_AUTH),
16368c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
16378c2ecf20Sopenharmony_ci	DRM_IOCTL_DEF_DRV(R128_GETPARAM, r128_getparam, DRM_AUTH),
16388c2ecf20Sopenharmony_ci};
16398c2ecf20Sopenharmony_ci
16408c2ecf20Sopenharmony_ciint r128_max_ioctl = ARRAY_SIZE(r128_ioctls);
1641