blob: 87bba25c6555a19df4136f1bbe434c9ddfffe70a [file] [log] [blame]
Jordan Crouse0fdf3a02012-03-16 14:53:41 -06001/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13#ifndef __KGSL_H
14#define __KGSL_H
15
16#include <linux/types.h>
17#include <linux/msm_kgsl.h>
18#include <linux/platform_device.h>
19#include <linux/clk.h>
20#include <linux/interrupt.h>
21#include <linux/mutex.h>
22#include <linux/cdev.h>
23#include <linux/regulator/consumer.h>
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -060024#include <linux/mm.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070025
26#define KGSL_NAME "kgsl"
27
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070028/*cache coherency ops */
29#define DRM_KGSL_GEM_CACHE_OP_TO_DEV 0x0001
30#define DRM_KGSL_GEM_CACHE_OP_FROM_DEV 0x0002
31
32/* The size of each entry in a page table */
33#define KGSL_PAGETABLE_ENTRY_SIZE 4
34
35/* Pagetable Virtual Address base */
36#define KGSL_PAGETABLE_BASE 0x66000000
37
38/* Extra accounting entries needed in the pagetable */
39#define KGSL_PT_EXTRA_ENTRIES 16
40
41#define KGSL_PAGETABLE_ENTRIES(_sz) (((_sz) >> PAGE_SHIFT) + \
42 KGSL_PT_EXTRA_ENTRIES)
43
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070044#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
45#define KGSL_PAGETABLE_COUNT (CONFIG_MSM_KGSL_PAGE_TABLE_COUNT)
46#else
47#define KGSL_PAGETABLE_COUNT 1
48#endif
49
50/* Casting using container_of() for structures that kgsl owns. */
51#define KGSL_CONTAINER_OF(ptr, type, member) \
52 container_of(ptr, type, member)
53
54/* A macro for memory statistics - add the new size to the stat and if
55 the statisic is greater then _max, set _max
56*/
57
58#define KGSL_STATS_ADD(_size, _stat, _max) \
59 do { _stat += (_size); if (_stat > _max) _max = _stat; } while (0)
60
61struct kgsl_device;
62
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070063struct kgsl_driver {
64 struct cdev cdev;
65 dev_t major;
66 struct class *class;
67 /* Virtual device for managing the core */
68 struct device virtdev;
69 /* Kobjects for storing pagetable and process statistics */
70 struct kobject *ptkobj;
71 struct kobject *prockobj;
72 struct kgsl_device *devp[KGSL_DEVICE_MAX];
73
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070074 /* Global lilst of open processes */
75 struct list_head process_list;
76 /* Global list of pagetables */
77 struct list_head pagetable_list;
78 /* Spinlock for accessing the pagetable list */
79 spinlock_t ptlock;
80 /* Mutex for accessing the process list */
81 struct mutex process_mutex;
82
83 /* Mutex for protecting the device list */
84 struct mutex devlock;
85
Shubhraprakash Das767fdda2011-08-15 15:49:45 -060086 void *ptpool;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070087
88 struct {
89 unsigned int vmalloc;
90 unsigned int vmalloc_max;
91 unsigned int coherent;
92 unsigned int coherent_max;
93 unsigned int mapped;
94 unsigned int mapped_max;
95 unsigned int histogram[16];
96 } stats;
97};
98
99extern struct kgsl_driver kgsl_driver;
100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101struct kgsl_pagetable;
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -0600102struct kgsl_memdesc;
103
104struct kgsl_memdesc_ops {
105 int (*vmflags)(struct kgsl_memdesc *);
106 int (*vmfault)(struct kgsl_memdesc *, struct vm_area_struct *,
107 struct vm_fault *);
108 void (*free)(struct kgsl_memdesc *memdesc);
109 int (*map_kernel_mem)(struct kgsl_memdesc *);
110};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700111
112/* shared memory allocation */
113struct kgsl_memdesc {
114 struct kgsl_pagetable *pagetable;
115 void *hostptr;
116 unsigned int gpuaddr;
117 unsigned int physaddr;
118 unsigned int size;
119 unsigned int priv;
Jordan Croused17e9aa2011-10-12 16:57:48 -0600120 struct scatterlist *sg;
121 unsigned int sglen;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700122 struct kgsl_memdesc_ops *ops;
123};
124
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600125/* List of different memory entry types */
126
127#define KGSL_MEM_ENTRY_KERNEL 0
128#define KGSL_MEM_ENTRY_PMEM 1
129#define KGSL_MEM_ENTRY_ASHMEM 2
130#define KGSL_MEM_ENTRY_USER 3
Jordan Crouse8eab35a2011-10-12 16:57:48 -0600131#define KGSL_MEM_ENTRY_ION 4
132#define KGSL_MEM_ENTRY_MAX 5
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600133
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600134/* List of flags */
135
136#define KGSL_MEM_ENTRY_FROZEN (1 << 0)
137
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700138struct kgsl_mem_entry {
139 struct kref refcount;
140 struct kgsl_memdesc memdesc;
141 int memtype;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600142 int flags;
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600143 void *priv_data;
Jordan Crousec9559e42012-04-05 16:55:56 -0600144 struct rb_node node;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700145 uint32_t free_timestamp;
146 /* back pointer to private structure under whose context this
147 * allocation is made */
148 struct kgsl_process_private *priv;
149};
150
151#ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT
152#define MMU_CONFIG 2
153#else
154#define MMU_CONFIG 1
155#endif
156
157void kgsl_mem_entry_destroy(struct kref *kref);
Jordan Crouse0fdf3a02012-03-16 14:53:41 -0600158
159struct kgsl_mem_entry *kgsl_get_mem_entry(unsigned int ptbase,
160 unsigned int gpuaddr, unsigned int size);
161
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700162struct kgsl_mem_entry *kgsl_sharedmem_find_region(
163 struct kgsl_process_private *private, unsigned int gpuaddr,
164 size_t size);
165
166extern const struct dev_pm_ops kgsl_pm_ops;
167
168struct early_suspend;
169int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state);
170int kgsl_resume_driver(struct platform_device *pdev);
171void kgsl_early_suspend_driver(struct early_suspend *h);
172void kgsl_late_resume_driver(struct early_suspend *h);
173
174#ifdef CONFIG_MSM_KGSL_DRM
175extern int kgsl_drm_init(struct platform_device *dev);
176extern void kgsl_drm_exit(void);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700177#else
178static inline int kgsl_drm_init(struct platform_device *dev)
179{
180 return 0;
181}
182
183static inline void kgsl_drm_exit(void)
184{
185}
186#endif
187
188static inline int kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc,
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700189 unsigned int gpuaddr, unsigned int size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700190{
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700191 if (gpuaddr >= memdesc->gpuaddr &&
192 ((gpuaddr + size) <= (memdesc->gpuaddr + memdesc->size))) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700193 return 1;
194 }
195 return 0;
196}
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -0600197static inline uint8_t *kgsl_gpuaddr_to_vaddr(struct kgsl_memdesc *memdesc,
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700198 unsigned int gpuaddr)
199{
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -0600200 if (memdesc->gpuaddr == 0 ||
201 gpuaddr < memdesc->gpuaddr ||
202 gpuaddr >= (memdesc->gpuaddr + memdesc->size) ||
203 (NULL == memdesc->hostptr && memdesc->ops->map_kernel_mem &&
204 memdesc->ops->map_kernel_mem(memdesc)))
205 return NULL;
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700206
207 return memdesc->hostptr + (gpuaddr - memdesc->gpuaddr);
208}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700209
Jordan Crousee6239dd2011-11-17 13:39:21 -0700210static inline int timestamp_cmp(unsigned int new, unsigned int old)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700211{
212 int ts_diff = new - old;
Jordan Crousee6239dd2011-11-17 13:39:21 -0700213
214 if (ts_diff == 0)
215 return 0;
216
Shubhraprakash Das3dd73752012-02-21 11:22:59 -0700217 return ((ts_diff > 0) || (ts_diff < -25000)) ? 1 : -1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218}
219
220static inline void
221kgsl_mem_entry_get(struct kgsl_mem_entry *entry)
222{
223 kref_get(&entry->refcount);
224}
225
226static inline void
227kgsl_mem_entry_put(struct kgsl_mem_entry *entry)
228{
229 kref_put(&entry->refcount, kgsl_mem_entry_destroy);
230}
231
232#endif /* __KGSL_H */