/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of Code Aurora Forum, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef __KGSL_H #define __KGSL_H #include #include #include #include #include #include #include #include #include #include "kgsl_device.h" #include "kgsl_pwrctrl.h" #include "kgsl_sharedmem.h" #include "kgsl_log.h" #include "kgsl_cffdump.h" #define KGSL_NAME "kgsl" #define CHIP_REV_251 0x020501 /* Flags to control whether to flush or invalidate a cached memory range */ #define KGSL_CACHE_INV 0x00000000 #define KGSL_CACHE_CLEAN 0x00000001 #define KGSL_CACHE_FLUSH 0x00000002 #define KGSL_CACHE_USER_ADDR 0x00000010 #define KGSL_CACHE_VMALLOC_ADDR 0x00000020 /*cache coherency ops */ #define DRM_KGSL_GEM_CACHE_OP_TO_DEV 0x0001 #define DRM_KGSL_GEM_CACHE_OP_FROM_DEV 0x0002 /* The size of each entry in a page table */ #define KGSL_PAGETABLE_ENTRY_SIZE 4 /* Pagetable Virtual Address base */ #define KGSL_PAGETABLE_BASE 0x66000000 /* Extra accounting entries needed in the pagetable */ #define KGSL_PT_EXTRA_ENTRIES 16 #define KGSL_PAGETABLE_ENTRIES(_sz) (((_sz) >> PAGE_SHIFT) + \ KGSL_PT_EXTRA_ENTRIES) #ifdef CONFIG_MSM_KGSL_MMU #define KGSL_PAGETABLE_SIZE \ ALIGN(KGSL_PAGETABLE_ENTRIES(CONFIG_MSM_KGSL_PAGE_TABLE_SIZE) * \ KGSL_PAGETABLE_ENTRY_SIZE, PAGE_SIZE) #else #define KGSL_PAGETABLE_SIZE 0 #endif #ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE #define KGSL_PAGETABLE_COUNT (CONFIG_MSM_KGSL_PAGE_TABLE_COUNT) #else #define KGSL_PAGETABLE_COUNT 1 #endif /* Casting using container_of() for structures that kgsl owns. */ #define KGSL_CONTAINER_OF(ptr, type, member) \ container_of(ptr, type, member) /* A macro for memory statistics - add the new size to the stat and if the statisic is greater then _max, set _max */ #define KGSL_STATS_ADD(_size, _stat, _max) \ do { _stat += (_size); if (_stat > _max) _max = _stat; } while (0) struct kgsl_driver { struct cdev cdev; dev_t major; struct class *class; /* Virtual device for managing the core */ struct device virtdev; /* Kobjects for storing pagetable and process statistics */ struct kobject *ptkobj; struct kobject *prockobj; atomic_t device_count; struct kgsl_device *devp[KGSL_DEVICE_MAX]; uint32_t flags_debug; /* Global lilst of open processes */ struct list_head process_list; /* Global list of pagetables */ struct list_head pagetable_list; /* Mutex for accessing the pagetable list */ struct mutex pt_mutex; /* Mutex for accessing the process list */ struct mutex process_mutex; /* Mutex for protecting the device list */ struct mutex devlock; struct kgsl_ptpool ptpool; struct { unsigned int vmalloc; unsigned int vmalloc_max; unsigned int coherent; unsigned int coherent_max; unsigned int mapped; unsigned int mapped_max; unsigned int histogram[16]; } stats; }; extern struct kgsl_driver kgsl_driver; #define KGSL_USER_MEMORY 1 #define KGSL_MAPPED_MEMORY 2 struct kgsl_mem_entry { struct kref refcount; struct kgsl_memdesc memdesc; int memtype; struct file *file_ptr; struct list_head list; uint32_t free_timestamp; /* back pointer to private structure under whose context this * allocation is made */ struct kgsl_process_private *priv; }; #ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT #define MMU_CONFIG 2 #else #define MMU_CONFIG 1 #endif void kgsl_mem_entry_destroy(struct kref *kref); uint8_t *kgsl_gpuaddr_to_vaddr(const struct kgsl_memdesc *memdesc, unsigned int gpuaddr, unsigned int *size); struct kgsl_mem_entry *kgsl_sharedmem_find_region( struct kgsl_process_private *private, unsigned int gpuaddr, size_t size); int kgsl_idle(struct kgsl_device *device, unsigned int timeout); int kgsl_setstate(struct kgsl_device *device, uint32_t flags); static inline void kgsl_regread(struct kgsl_device *device, unsigned int offsetwords, unsigned int *value) { device->ftbl.device_regread(device, offsetwords, value); } static inline void kgsl_regwrite(struct kgsl_device *device, unsigned int offsetwords, unsigned int value) { device->ftbl.device_regwrite(device, offsetwords, value); } static inline void kgsl_regread_isr(struct kgsl_device *device, unsigned int offsetwords, unsigned int *value) { device->ftbl.device_regread_isr(device, offsetwords, value); } static inline void kgsl_regwrite_isr(struct kgsl_device *device, unsigned int offsetwords, unsigned int value) { device->ftbl.device_regwrite_isr(device, offsetwords, value); } int kgsl_check_timestamp(struct kgsl_device *device, unsigned int timestamp); int kgsl_register_ts_notifier(struct kgsl_device *device, struct notifier_block *nb); int kgsl_unregister_ts_notifier(struct kgsl_device *device, struct notifier_block *nb); int kgsl_device_platform_probe(struct kgsl_device *device, irqreturn_t (*dev_isr) (int, void*)); void kgsl_device_platform_remove(struct kgsl_device *device); extern const struct dev_pm_ops kgsl_pm_ops; int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state); int kgsl_resume_driver(struct platform_device *pdev); #ifdef CONFIG_MSM_KGSL_DRM extern int kgsl_drm_init(struct platform_device *dev); extern void kgsl_drm_exit(void); extern void kgsl_gpu_mem_flush(int op); #else static inline int kgsl_drm_init(struct platform_device *dev) { return 0; } static inline void kgsl_drm_exit(void) { } #endif static inline int kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc, unsigned int gpuaddr) { if (gpuaddr >= memdesc->gpuaddr && (gpuaddr + sizeof(unsigned int)) <= (memdesc->gpuaddr + memdesc->size)) { return 1; } return 0; } static inline struct kgsl_device *kgsl_device_from_dev(struct device *dev) { int i; for (i = 0; i < KGSL_DEVICE_MAX; i++) { if (kgsl_driver.devp[i] && kgsl_driver.devp[i]->dev == dev) return kgsl_driver.devp[i]; } return NULL; } static inline bool timestamp_cmp(unsigned int new, unsigned int old) { int ts_diff = new - old; return (ts_diff >= 0) || (ts_diff < -20000); } static inline void kgsl_mem_entry_get(struct kgsl_mem_entry *entry) { kref_get(&entry->refcount); } static inline void kgsl_mem_entry_put(struct kgsl_mem_entry *entry) { kref_put(&entry->refcount, kgsl_mem_entry_destroy); } static inline int kgsl_create_device_sysfs_files(struct device *root, struct device_attribute **list) { int ret = 0, i; for (i = 0; list[i] != NULL; i++) ret |= device_create_file(root, list[i]); return ret; } static inline void kgsl_remove_device_sysfs_files(struct device *root, struct device_attribute **list) { int i; for (i = 0; list[i] != NULL; i++) device_remove_file(root, list[i]); } #endif /* __KGSL_H */