18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
38c2ecf20Sopenharmony_ci * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
68c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
78c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
88c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sub license,
98c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
108c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the
138c2ecf20Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
148c2ecf20Sopenharmony_ci * of the Software.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
198c2ecf20Sopenharmony_ci * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
208c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
218c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
228c2ecf20Sopenharmony_ci * DEALINGS IN THE SOFTWARE.
238c2ecf20Sopenharmony_ci */
248c2ecf20Sopenharmony_ci#ifndef _VIA_DRV_H_
258c2ecf20Sopenharmony_ci#define _VIA_DRV_H_
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#include <linux/irqreturn.h>
288c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
298c2ecf20Sopenharmony_ci#include <linux/sched.h>
308c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
318c2ecf20Sopenharmony_ci#include <linux/wait.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include <drm/drm_ioctl.h>
348c2ecf20Sopenharmony_ci#include <drm/drm_legacy.h>
358c2ecf20Sopenharmony_ci#include <drm/drm_mm.h>
368c2ecf20Sopenharmony_ci#include <drm/via_drm.h>
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define DRIVER_AUTHOR	"Various"
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#define DRIVER_NAME		"via"
418c2ecf20Sopenharmony_ci#define DRIVER_DESC		"VIA Unichrome / Pro"
428c2ecf20Sopenharmony_ci#define DRIVER_DATE		"20070202"
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#define DRIVER_MAJOR		2
458c2ecf20Sopenharmony_ci#define DRIVER_MINOR		11
468c2ecf20Sopenharmony_ci#define DRIVER_PATCHLEVEL	1
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#include "via_verifier.h"
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#include "via_dmablit.h"
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#define VIA_PCI_BUF_SIZE 60000
538c2ecf20Sopenharmony_ci#define VIA_FIRE_BUF_SIZE  1024
548c2ecf20Sopenharmony_ci#define VIA_NUM_IRQS 4
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_citypedef struct drm_via_ring_buffer {
578c2ecf20Sopenharmony_ci	drm_local_map_t map;
588c2ecf20Sopenharmony_ci	char *virtual_start;
598c2ecf20Sopenharmony_ci} drm_via_ring_buffer_t;
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_citypedef uint32_t maskarray_t[5];
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_citypedef struct drm_via_irq {
648c2ecf20Sopenharmony_ci	atomic_t irq_received;
658c2ecf20Sopenharmony_ci	uint32_t pending_mask;
668c2ecf20Sopenharmony_ci	uint32_t enable_mask;
678c2ecf20Sopenharmony_ci	wait_queue_head_t irq_queue;
688c2ecf20Sopenharmony_ci} drm_via_irq_t;
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_citypedef struct drm_via_private {
718c2ecf20Sopenharmony_ci	drm_via_sarea_t *sarea_priv;
728c2ecf20Sopenharmony_ci	drm_local_map_t *sarea;
738c2ecf20Sopenharmony_ci	drm_local_map_t *fb;
748c2ecf20Sopenharmony_ci	drm_local_map_t *mmio;
758c2ecf20Sopenharmony_ci	unsigned long agpAddr;
768c2ecf20Sopenharmony_ci	wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
778c2ecf20Sopenharmony_ci	char *dma_ptr;
788c2ecf20Sopenharmony_ci	unsigned int dma_low;
798c2ecf20Sopenharmony_ci	unsigned int dma_high;
808c2ecf20Sopenharmony_ci	unsigned int dma_offset;
818c2ecf20Sopenharmony_ci	uint32_t dma_wrap;
828c2ecf20Sopenharmony_ci	volatile uint32_t *last_pause_ptr;
838c2ecf20Sopenharmony_ci	volatile uint32_t *hw_addr_ptr;
848c2ecf20Sopenharmony_ci	drm_via_ring_buffer_t ring;
858c2ecf20Sopenharmony_ci	ktime_t last_vblank;
868c2ecf20Sopenharmony_ci	int last_vblank_valid;
878c2ecf20Sopenharmony_ci	ktime_t nsec_per_vblank;
888c2ecf20Sopenharmony_ci	atomic_t vbl_received;
898c2ecf20Sopenharmony_ci	drm_via_state_t hc_state;
908c2ecf20Sopenharmony_ci	char pci_buf[VIA_PCI_BUF_SIZE];
918c2ecf20Sopenharmony_ci	const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
928c2ecf20Sopenharmony_ci	uint32_t num_fire_offsets;
938c2ecf20Sopenharmony_ci	int chipset;
948c2ecf20Sopenharmony_ci	drm_via_irq_t via_irqs[VIA_NUM_IRQS];
958c2ecf20Sopenharmony_ci	unsigned num_irqs;
968c2ecf20Sopenharmony_ci	maskarray_t *irq_masks;
978c2ecf20Sopenharmony_ci	uint32_t irq_enable_mask;
988c2ecf20Sopenharmony_ci	uint32_t irq_pending_mask;
998c2ecf20Sopenharmony_ci	int *irq_map;
1008c2ecf20Sopenharmony_ci	unsigned int idle_fault;
1018c2ecf20Sopenharmony_ci	int vram_initialized;
1028c2ecf20Sopenharmony_ci	struct drm_mm vram_mm;
1038c2ecf20Sopenharmony_ci	int agp_initialized;
1048c2ecf20Sopenharmony_ci	struct drm_mm agp_mm;
1058c2ecf20Sopenharmony_ci	/** Mapping of userspace keys to mm objects */
1068c2ecf20Sopenharmony_ci	struct idr object_idr;
1078c2ecf20Sopenharmony_ci	unsigned long vram_offset;
1088c2ecf20Sopenharmony_ci	unsigned long agp_offset;
1098c2ecf20Sopenharmony_ci	drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES];
1108c2ecf20Sopenharmony_ci	uint32_t dma_diff;
1118c2ecf20Sopenharmony_ci} drm_via_private_t;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistruct via_file_private {
1148c2ecf20Sopenharmony_ci	struct list_head obj_list;
1158c2ecf20Sopenharmony_ci};
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cienum via_family {
1188c2ecf20Sopenharmony_ci  VIA_OTHER = 0,     /* Baseline */
1198c2ecf20Sopenharmony_ci  VIA_PRO_GROUP_A,   /* Another video engine and DMA commands */
1208c2ecf20Sopenharmony_ci  VIA_DX9_0          /* Same video as pro_group_a, but 3D is unsupported */
1218c2ecf20Sopenharmony_ci};
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci/* VIA MMIO register access */
1248c2ecf20Sopenharmony_cistatic inline u32 via_read(struct drm_via_private *dev_priv, u32 reg)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	return readl((void __iomem *)(dev_priv->mmio->handle + reg));
1278c2ecf20Sopenharmony_ci}
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cistatic inline void via_write(struct drm_via_private *dev_priv, u32 reg,
1308c2ecf20Sopenharmony_ci			     u32 val)
1318c2ecf20Sopenharmony_ci{
1328c2ecf20Sopenharmony_ci	writel(val, (void __iomem *)(dev_priv->mmio->handle + reg));
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic inline void via_write8(struct drm_via_private *dev_priv, u32 reg,
1368c2ecf20Sopenharmony_ci			      u32 val)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	writeb(val, (void __iomem *)(dev_priv->mmio->handle + reg));
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic inline void via_write8_mask(struct drm_via_private *dev_priv,
1428c2ecf20Sopenharmony_ci				   u32 reg, u32 mask, u32 val)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	u32 tmp;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	tmp = readb((void __iomem *)(dev_priv->mmio->handle + reg));
1478c2ecf20Sopenharmony_ci	tmp = (tmp & ~mask) | (val & mask);
1488c2ecf20Sopenharmony_ci	writeb(tmp, (void __iomem *)(dev_priv->mmio->handle + reg));
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci/*
1528c2ecf20Sopenharmony_ci * Poll in a loop waiting for 'contidition' to be true.
1538c2ecf20Sopenharmony_ci * Note: A direct replacement with wait_event_interruptible_timeout()
1548c2ecf20Sopenharmony_ci *       will not work unless driver is updated to emit wake_up()
1558c2ecf20Sopenharmony_ci *       in relevant places that can impact the 'condition'
1568c2ecf20Sopenharmony_ci *
1578c2ecf20Sopenharmony_ci * Returns:
1588c2ecf20Sopenharmony_ci *   ret keeps current value if 'condition' becomes true
1598c2ecf20Sopenharmony_ci *   ret = -BUSY if timeout happens
1608c2ecf20Sopenharmony_ci *   ret = -EINTR if a signal interrupted the waiting period
1618c2ecf20Sopenharmony_ci */
1628c2ecf20Sopenharmony_ci#define VIA_WAIT_ON( ret, queue, timeout, condition )		\
1638c2ecf20Sopenharmony_cido {								\
1648c2ecf20Sopenharmony_ci	DECLARE_WAITQUEUE(entry, current);			\
1658c2ecf20Sopenharmony_ci	unsigned long end = jiffies + (timeout);		\
1668c2ecf20Sopenharmony_ci	add_wait_queue(&(queue), &entry);			\
1678c2ecf20Sopenharmony_ci								\
1688c2ecf20Sopenharmony_ci	for (;;) {						\
1698c2ecf20Sopenharmony_ci		__set_current_state(TASK_INTERRUPTIBLE);	\
1708c2ecf20Sopenharmony_ci		if (condition)					\
1718c2ecf20Sopenharmony_ci			break;					\
1728c2ecf20Sopenharmony_ci		if (time_after_eq(jiffies, end)) {		\
1738c2ecf20Sopenharmony_ci			ret = -EBUSY;				\
1748c2ecf20Sopenharmony_ci			break;					\
1758c2ecf20Sopenharmony_ci		}						\
1768c2ecf20Sopenharmony_ci		schedule_timeout((HZ/100 > 1) ? HZ/100 : 1);	\
1778c2ecf20Sopenharmony_ci		if (signal_pending(current)) {			\
1788c2ecf20Sopenharmony_ci			ret = -EINTR;				\
1798c2ecf20Sopenharmony_ci			break;					\
1808c2ecf20Sopenharmony_ci		}						\
1818c2ecf20Sopenharmony_ci	}							\
1828c2ecf20Sopenharmony_ci	__set_current_state(TASK_RUNNING);			\
1838c2ecf20Sopenharmony_ci	remove_wait_queue(&(queue), &entry);			\
1848c2ecf20Sopenharmony_ci} while (0)
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ciextern const struct drm_ioctl_desc via_ioctls[];
1878c2ecf20Sopenharmony_ciextern int via_max_ioctl;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ciextern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
1908c2ecf20Sopenharmony_ciextern int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv);
1918c2ecf20Sopenharmony_ciextern int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv);
1928c2ecf20Sopenharmony_ciextern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
1938c2ecf20Sopenharmony_ciextern int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv);
1948c2ecf20Sopenharmony_ciextern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv);
1958c2ecf20Sopenharmony_ciextern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv);
1968c2ecf20Sopenharmony_ciextern int via_dma_blit_sync(struct drm_device *dev, void *data, struct drm_file *file_priv);
1978c2ecf20Sopenharmony_ciextern int via_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ciextern int via_driver_load(struct drm_device *dev, unsigned long chipset);
2008c2ecf20Sopenharmony_ciextern void via_driver_unload(struct drm_device *dev);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ciextern int via_init_context(struct drm_device *dev, int context);
2038c2ecf20Sopenharmony_ciextern int via_final_context(struct drm_device *dev, int context);
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ciextern int via_do_cleanup_map(struct drm_device *dev);
2068c2ecf20Sopenharmony_ciextern u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe);
2078c2ecf20Sopenharmony_ciextern int via_enable_vblank(struct drm_device *dev, unsigned int pipe);
2088c2ecf20Sopenharmony_ciextern void via_disable_vblank(struct drm_device *dev, unsigned int pipe);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ciextern irqreturn_t via_driver_irq_handler(int irq, void *arg);
2118c2ecf20Sopenharmony_ciextern void via_driver_irq_preinstall(struct drm_device *dev);
2128c2ecf20Sopenharmony_ciextern int via_driver_irq_postinstall(struct drm_device *dev);
2138c2ecf20Sopenharmony_ciextern void via_driver_irq_uninstall(struct drm_device *dev);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ciextern int via_dma_cleanup(struct drm_device *dev);
2168c2ecf20Sopenharmony_ciextern void via_init_command_verifier(void);
2178c2ecf20Sopenharmony_ciextern int via_driver_dma_quiescent(struct drm_device *dev);
2188c2ecf20Sopenharmony_ciextern void via_init_futex(drm_via_private_t *dev_priv);
2198c2ecf20Sopenharmony_ciextern void via_cleanup_futex(drm_via_private_t *dev_priv);
2208c2ecf20Sopenharmony_ciextern void via_release_futex(drm_via_private_t *dev_priv, int context);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ciextern void via_reclaim_buffers_locked(struct drm_device *dev,
2238c2ecf20Sopenharmony_ci				       struct drm_file *file_priv);
2248c2ecf20Sopenharmony_ciextern void via_lastclose(struct drm_device *dev);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ciextern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq);
2278c2ecf20Sopenharmony_ciextern void via_init_dmablit(struct drm_device *dev);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci#endif
230