blob: fcd8448bf6de216099833e12d6d30bc5c0a6a4aa [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
Carter Cooper7e7f02e2012-02-15 09:36:31 -070028/* The number of memstore arrays limits the number of contexts allowed.
29 * If more contexts are needed, update multiple for MEMSTORE_SIZE
30 */
31#define KGSL_MEMSTORE_SIZE ((int)(PAGE_SIZE * 2))
32#define KGSL_MEMSTORE_GLOBAL (0)
33#define KGSL_MEMSTORE_MAX (KGSL_MEMSTORE_SIZE / \
34 sizeof(struct kgsl_devmemstore) - 1)
35
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070036/*cache coherency ops */
37#define DRM_KGSL_GEM_CACHE_OP_TO_DEV 0x0001
38#define DRM_KGSL_GEM_CACHE_OP_FROM_DEV 0x0002
39
40/* The size of each entry in a page table */
41#define KGSL_PAGETABLE_ENTRY_SIZE 4
42
43/* Pagetable Virtual Address base */
44#define KGSL_PAGETABLE_BASE 0x66000000
45
46/* Extra accounting entries needed in the pagetable */
47#define KGSL_PT_EXTRA_ENTRIES 16
48
49#define KGSL_PAGETABLE_ENTRIES(_sz) (((_sz) >> PAGE_SHIFT) + \
50 KGSL_PT_EXTRA_ENTRIES)
51
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070052#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE
53#define KGSL_PAGETABLE_COUNT (CONFIG_MSM_KGSL_PAGE_TABLE_COUNT)
54#else
55#define KGSL_PAGETABLE_COUNT 1
56#endif
57
58/* Casting using container_of() for structures that kgsl owns. */
59#define KGSL_CONTAINER_OF(ptr, type, member) \
60 container_of(ptr, type, member)
61
62/* A macro for memory statistics - add the new size to the stat and if
63 the statisic is greater then _max, set _max
64*/
65
66#define KGSL_STATS_ADD(_size, _stat, _max) \
67 do { _stat += (_size); if (_stat > _max) _max = _stat; } while (0)
68
69struct kgsl_device;
70
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070071struct kgsl_driver {
72 struct cdev cdev;
73 dev_t major;
74 struct class *class;
75 /* Virtual device for managing the core */
76 struct device virtdev;
77 /* Kobjects for storing pagetable and process statistics */
78 struct kobject *ptkobj;
79 struct kobject *prockobj;
80 struct kgsl_device *devp[KGSL_DEVICE_MAX];
81
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070082 /* Global lilst of open processes */
83 struct list_head process_list;
84 /* Global list of pagetables */
85 struct list_head pagetable_list;
86 /* Spinlock for accessing the pagetable list */
87 spinlock_t ptlock;
88 /* Mutex for accessing the process list */
89 struct mutex process_mutex;
90
91 /* Mutex for protecting the device list */
92 struct mutex devlock;
93
Shubhraprakash Das767fdda2011-08-15 15:49:45 -060094 void *ptpool;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070095
96 struct {
97 unsigned int vmalloc;
98 unsigned int vmalloc_max;
99 unsigned int coherent;
100 unsigned int coherent_max;
101 unsigned int mapped;
102 unsigned int mapped_max;
103 unsigned int histogram[16];
104 } stats;
105};
106
107extern struct kgsl_driver kgsl_driver;
108
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700109struct kgsl_pagetable;
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -0600110struct kgsl_memdesc;
111
112struct kgsl_memdesc_ops {
113 int (*vmflags)(struct kgsl_memdesc *);
114 int (*vmfault)(struct kgsl_memdesc *, struct vm_area_struct *,
115 struct vm_fault *);
116 void (*free)(struct kgsl_memdesc *memdesc);
117 int (*map_kernel_mem)(struct kgsl_memdesc *);
118};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700119
120/* shared memory allocation */
121struct kgsl_memdesc {
122 struct kgsl_pagetable *pagetable;
123 void *hostptr;
124 unsigned int gpuaddr;
125 unsigned int physaddr;
126 unsigned int size;
127 unsigned int priv;
Jordan Croused17e9aa2011-10-12 16:57:48 -0600128 struct scatterlist *sg;
129 unsigned int sglen;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700130 struct kgsl_memdesc_ops *ops;
131};
132
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600133/* List of different memory entry types */
134
135#define KGSL_MEM_ENTRY_KERNEL 0
136#define KGSL_MEM_ENTRY_PMEM 1
137#define KGSL_MEM_ENTRY_ASHMEM 2
138#define KGSL_MEM_ENTRY_USER 3
Jordan Crouse8eab35a2011-10-12 16:57:48 -0600139#define KGSL_MEM_ENTRY_ION 4
140#define KGSL_MEM_ENTRY_MAX 5
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600141
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600142/* List of flags */
143
144#define KGSL_MEM_ENTRY_FROZEN (1 << 0)
145
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700146struct kgsl_mem_entry {
147 struct kref refcount;
148 struct kgsl_memdesc memdesc;
149 int memtype;
Jordan Crouse9610b6b2012-03-16 14:53:42 -0600150 int flags;
Jordan Crouse1b897cf2011-10-12 16:57:48 -0600151 void *priv_data;
Jordan Crousec9559e42012-04-05 16:55:56 -0600152 struct rb_node node;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153 uint32_t free_timestamp;
Carter Cooper7e7f02e2012-02-15 09:36:31 -0700154 unsigned int context_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700155 /* back pointer to private structure under whose context this
156 * allocation is made */
157 struct kgsl_process_private *priv;
158};
159
160#ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT
161#define MMU_CONFIG 2
162#else
163#define MMU_CONFIG 1
164#endif
165
166void kgsl_mem_entry_destroy(struct kref *kref);
Jordan Crouse0fdf3a02012-03-16 14:53:41 -0600167
168struct kgsl_mem_entry *kgsl_get_mem_entry(unsigned int ptbase,
169 unsigned int gpuaddr, unsigned int size);
170
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700171struct kgsl_mem_entry *kgsl_sharedmem_find_region(
172 struct kgsl_process_private *private, unsigned int gpuaddr,
173 size_t size);
174
175extern const struct dev_pm_ops kgsl_pm_ops;
176
177struct early_suspend;
178int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state);
179int kgsl_resume_driver(struct platform_device *pdev);
180void kgsl_early_suspend_driver(struct early_suspend *h);
181void kgsl_late_resume_driver(struct early_suspend *h);
182
183#ifdef CONFIG_MSM_KGSL_DRM
184extern int kgsl_drm_init(struct platform_device *dev);
185extern void kgsl_drm_exit(void);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700186#else
187static inline int kgsl_drm_init(struct platform_device *dev)
188{
189 return 0;
190}
191
192static inline void kgsl_drm_exit(void)
193{
194}
195#endif
196
197static inline int kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc,
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700198 unsigned int gpuaddr, unsigned int size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700199{
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700200 if (gpuaddr >= memdesc->gpuaddr &&
201 ((gpuaddr + size) <= (memdesc->gpuaddr + memdesc->size))) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700202 return 1;
203 }
204 return 0;
205}
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -0600206static inline uint8_t *kgsl_gpuaddr_to_vaddr(struct kgsl_memdesc *memdesc,
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700207 unsigned int gpuaddr)
208{
Harsh Vardhan Dwivedi8cb835b2012-03-29 17:23:11 -0600209 if (memdesc->gpuaddr == 0 ||
210 gpuaddr < memdesc->gpuaddr ||
211 gpuaddr >= (memdesc->gpuaddr + memdesc->size) ||
212 (NULL == memdesc->hostptr && memdesc->ops->map_kernel_mem &&
213 memdesc->ops->map_kernel_mem(memdesc)))
214 return NULL;
Jeremy Gebben16e80fa2011-11-30 15:56:29 -0700215
216 return memdesc->hostptr + (gpuaddr - memdesc->gpuaddr);
217}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218
Jordan Crousee6239dd2011-11-17 13:39:21 -0700219static inline int timestamp_cmp(unsigned int new, unsigned int old)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700220{
221 int ts_diff = new - old;
Jordan Crousee6239dd2011-11-17 13:39:21 -0700222
223 if (ts_diff == 0)
224 return 0;
225
Shubhraprakash Das3dd73752012-02-21 11:22:59 -0700226 return ((ts_diff > 0) || (ts_diff < -25000)) ? 1 : -1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227}
228
229static inline void
230kgsl_mem_entry_get(struct kgsl_mem_entry *entry)
231{
232 kref_get(&entry->refcount);
233}
234
235static inline void
236kgsl_mem_entry_put(struct kgsl_mem_entry *entry)
237{
238 kref_put(&entry->refcount, kgsl_mem_entry_destroy);
239}
240
241#endif /* __KGSL_H */