aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2010-06-29 05:41:37 -0400
committerPaolo Pisati <paolo.pisati@canonical.com>2012-08-17 04:18:57 -0400
commitfe0ae617ff9b61bedc4f8a88289bf5b982aba2ef (patch)
treea6e7d5f1a97f0ba7341329973914634e30139f55
parent0c5ba809d7e5be11eb04efc68067ab70d30c508e (diff)
TILER: Update to v2.0 kernel API, remove d2cmap limitation
Changed tiler_alloc/x, tiler_map/x and tiler_free APIs to use tiler_block_t structure. Simplified tiler_mmap using information in this structure. Now storing and able to reconstruct exact dimension of each allocated tiler block. Fixed issue with virtual stride of 1D buffers when using an offset. Signed-off-by: Lajos Molnar <molnar@ti.com> Signed-off-by: David Sin <davidsin@ti.com>
-rw-r--r--arch/arm/mach-omap2/include/mach/tiler.h98
-rw-r--r--drivers/media/video/tiler/tiler.c279
-rw-r--r--drivers/media/video/tiler/tiler_def.h8
3 files changed, 240 insertions, 145 deletions
diff --git a/arch/arm/mach-omap2/include/mach/tiler.h b/arch/arm/mach-omap2/include/mach/tiler.h
index 9ce79734482..6f0757b9b24 100644
--- a/arch/arm/mach-omap2/include/mach/tiler.h
+++ b/arch/arm/mach-omap2/include/mach/tiler.h
@@ -47,6 +47,14 @@ enum tiler_fmt {
47 TILFMT_MAX = 3, 47 TILFMT_MAX = 3,
48}; 48};
49 49
50struct tiler_block_t {
51 u32 phys; /* system space (L3) tiler addr */
52 u32 width; /* width */
53 u32 height; /* height */
54 u32 key; /* secret key */
55 u32 id; /* unique block ID */
56};
57
50struct area { 58struct area {
51 u16 width; 59 u16 width;
52 u16 height; 60 u16 height;
@@ -82,46 +90,39 @@ struct tiler_view_orient {
82 u8 y_invert; 90 u8 y_invert;
83}; 91};
84 92
85/* utility functions */
86static inline u32 tilfmt_bpp(enum tiler_fmt fmt)
87{
88 return fmt == TILFMT_8BIT ? 1 :
89 fmt == TILFMT_16BIT ? 2 :
90 fmt == TILFMT_32BIT ? 4 : 0;
91}
92
93/** 93/**
94 * Reserves a 1D or 2D TILER block area and memory for the 94 * Reserves a 1D or 2D TILER block area and memory for the
95 * current process with group ID 0. 95 * current process with group ID 0.
96 * 96 *
97 * @param fmt TILER bit mode 97 * @param blk pointer to tiler block data. This must be set up ('phys' member
98 * @param width block width 98 * must be 0) with the tiler block information. 'height' must be 1
99 * @param height block height (must be 1 for 1D) 99 * for 1D block.
100 * @param sys_addr pointer where system space (L3) address 100 * @param fmt TILER block format
101 * will be stored. 101 * @param align block alignment (default: PAGE_SIZE)
102 * @param offs block offset
102 * 103 *
103 * @return error status 104 * @return error status
104 */ 105 */
105s32 tiler_alloc(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr); 106s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align,
107 u32 offs);
106 108
107/** 109/**
108 * Reserves a 1D or 2D TILER block area and memory with extended 110 * Reserves a 1D or 2D TILER block area and memory for a set process and group
109 * arguments. 111 * ID.
110 * 112 *
111 * @param fmt TILER bit mode 113 * @param blk pointer to tiler block data. This must be set up ('phys' member
112 * @param width block width 114 * must be 0) with the tiler block information. 'height' must be 1
113 * @param height block height (must be 1 for 1D) 115 * for 1D block.
114 * @param align block alignment (default: PAGE_SIZE) 116 * @param fmt TILER bit mode
115 * @param offs block offset 117 * @param align block alignment (default: PAGE_SIZE)
116 * @param gid group ID 118 * @param offs block offset
117 * @param pid process ID 119 * @param gid group ID
118 * @param sys_addr pointer where system space (L3) address 120 * @param pid process ID
119 * will be stored.
120 * 121 *
121 * @return error status 122 * @return error status
122 */ 123 */
123s32 tiler_allocx(enum tiler_fmt fmt, u32 width, u32 height, 124s32 tiler_allocx(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align,
124 u32 align, u32 offs, u32 gid, pid_t pid, u32 *sys_addr); 125 u32 offs, u32 gid, pid_t pid);
125 126
126/** 127/**
127 * Maps an existing buffer to a 1D or 2D TILER area for the 128 * Maps an existing buffer to a 1D or 2D TILER area for the
@@ -129,48 +130,53 @@ s32 tiler_allocx(enum tiler_fmt fmt, u32 width, u32 height,
129 * 130 *
130 * Currently, only 1D area mapping is supported. 131 * Currently, only 1D area mapping is supported.
131 * 132 *
133 * NOTE: alignment is always PAGE_SIZE and offset is 0 as full pages are mapped
134 * into tiler container.
135 *
136 * @param blk pointer to tiler block data. This must be set up
137 * ('phys' member must be 0) with the tiler block information.
138 * 'height' must be 1 for 1D block.
132 * @param fmt TILER bit mode 139 * @param fmt TILER bit mode
133 * @param width block width
134 * @param height block height (must be 1 for 1D)
135 * @param sys_addr pointer where system space (L3) address
136 * will be stored.
137 * @param usr_addr user space address of existing buffer. 140 * @param usr_addr user space address of existing buffer.
138 * 141 *
139 * @return error status 142 * @return error status
140 */ 143 */
141s32 tiler_map(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr, 144s32 tiler_map(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 usr_addr);
142 u32 usr_addr);
143 145
144/** 146/**
145 * Maps an existing buffer to a 1D or 2D TILER area with 147 * Maps an existing buffer to a 1D or 2D TILER area for a set process and group
146 * extended arguments. 148 * ID.
147 * 149 *
148 * Currently, only 1D area mapping is supported. 150 * Currently, only 1D area mapping is supported.
149 * 151 *
150 * NOTE: alignment is always PAGE_SIZE and offset is 0 152 * NOTE: alignment is always PAGE_SIZE and offset is 0 as full pages are mapped
153 * into tiler container.
151 * 154 *
155 * @param blk pointer to tiler block data. This must be set up
156 * ('phys' member must be 0) with the tiler block information.
157 * 'height' must be 1 for 1D block.
152 * @param fmt TILER bit mode 158 * @param fmt TILER bit mode
153 * @param width block width
154 * @param height block height (must be 1 for 1D)
155 * @param gid group ID 159 * @param gid group ID
156 * @param pid process ID 160 * @param pid process ID
157 * @param sys_addr pointer where system space (L3) address
158 * will be stored.
159 * @param usr_addr user space address of existing buffer. 161 * @param usr_addr user space address of existing buffer.
160 * 162 *
161 * @return error status 163 * @return error status
162 */ 164 */
163s32 tiler_mapx(enum tiler_fmt fmt, u32 width, u32 height, 165s32 tiler_mapx(struct tiler_block_t *blk, enum tiler_fmt fmt,
164 u32 gid, pid_t pid, u32 *sys_addr, u32 usr_addr); 166 u32 gid, pid_t pid, u32 usr_addr);
165 167
166/** 168/**
167 * Free TILER memory. 169 * Frees TILER memory. Since there may be multiple references for the same area
170 * if duplicated by tiler_dup, the area is only actually freed if all references
171 * have been freed.
168 * 172 *
169 * @param sys_addr system space (L3) address. 173 * @param blk pointer to a tiler block data as filled by tiler_alloc,
174 * tiler_map or tiler_dup. 'phys' member will be set to 0 on
175 * success.
170 * 176 *
171 * @return an error status. 177 * @return an error status.
172 */ 178 */
173s32 tiler_free(u32 sys_addr); 179s32 tiler_free(struct tiler_block_t *blk);
174 180
175/** 181/**
176 * Reserves tiler area for n identical set of blocks (buffer) 182 * Reserves tiler area for n identical set of blocks (buffer)
diff --git a/drivers/media/video/tiler/tiler.c b/drivers/media/video/tiler/tiler.c
index ed0baa63468..0d3aa51efa8 100644
--- a/drivers/media/video/tiler/tiler.c
+++ b/drivers/media/video/tiler/tiler.c
@@ -92,13 +92,13 @@ struct area_info {
92 92
93struct mem_info { 93struct mem_info {
94 struct list_head global; /* reserved / global blocks */ 94 struct list_head global; /* reserved / global blocks */
95 u32 sys_addr; /* system space (L3) tiler addr */ 95 struct tiler_block_t blk; /* block info */
96 u32 num_pg; /* number of pages in page-list */ 96 u32 num_pg; /* number of pages in page-list */
97 u32 usr; /* user space address */ 97 u32 usr; /* user space address */
98 u32 *pg_ptr; /* list of mapped struct page pointers */ 98 u32 *pg_ptr; /* list of mapped struct page ptrs */
99 struct tcm_area area; 99 struct tcm_area area;
100 u32 *mem; /* list of alloced phys addresses */ 100 u32 *mem; /* list of alloced phys addresses */
101 u32 refs; /* number of times referenced */ 101 u32 refs; /* number of times referenced */
102 bool alloced; /* still alloced */ 102 bool alloced; /* still alloced */
103 103
104 struct list_head by_area; /* blocks in the same area / 1D */ 104 struct list_head by_area; /* blocks in the same area / 1D */
@@ -129,6 +129,48 @@ static struct tmm *tmm[TILER_FORMATS];
129#define TMM_SS(ssptr) TMM(TILER_GET_ACC_MODE(ssptr)) 129#define TMM_SS(ssptr) TMM(TILER_GET_ACC_MODE(ssptr))
130#define TMM_SET(fmt, i) tmm[(fmt) - TILFMT_8BIT] = i 130#define TMM_SET(fmt, i) tmm[(fmt) - TILFMT_8BIT] = i
131 131
132static const u32 tiler_bpps[4] = { 1, 2, 4, 1 };
133static const u32 tiler_strides[4] = { 16384, 32768, 32768, 0 };
134
135static u32 is_tiler_addr(u32 addr)
136{
137 return addr >= TILVIEW_8BIT && addr < TILVIEW_END;
138}
139
140/* get tiler format */
141static inline u32 tiler_fmt(const struct tiler_block_t *b)
142{
143 if (!is_tiler_addr(b->phys))
144 BUG();
145 /* return TILER_GET_ACC_MODE(b->phys); */
146 return TILFMT_8BIT + (((b->phys - TILVIEW_8BIT) >> 27) & 3);
147}
148
149/* get tiler block bpp */
150static inline u32 tiler_bpp(const struct tiler_block_t *b)
151{
152 return tiler_bpps[tiler_fmt(b) - TILFMT_8BIT];
153}
154
155/* get tiler block virtual stride */
156static inline u32 tiler_vstride(const struct tiler_block_t *b)
157{
158 return PAGE_ALIGN((b->phys & ~PAGE_MASK) + tiler_bpp(b) * b->width);
159}
160
161/* get tiler block physical stride */
162static inline u32 tiler_pstride(const struct tiler_block_t *b)
163{
164 return tiler_strides[tiler_fmt(b) - TILFMT_8BIT] ? : tiler_vstride(b);
165}
166
167/* returns the virtual size of the block (for mmap) */
168static inline u32 tiler_size(const struct tiler_block_t *b)
169{
170 return b->height * tiler_vstride(b);
171}
172
173
132/* get process info, and increment refs for device tracking */ 174/* get process info, and increment refs for device tracking */
133static struct process_info *__get_pi(pid_t pid, bool kernel) 175static struct process_info *__get_pi(pid_t pid, bool kernel)
134{ 176{
@@ -237,7 +279,7 @@ static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height,
237 } 279 }
238 280
239 /* get the # of bytes per row in 1 slot */ 281 /* get the # of bytes per row in 1 slot */
240 bpp = tilfmt_bpp(fmt); 282 bpp = tiler_bpps[fmt - TILFMT_8BIT];
241 slot_row = slot_w * bpp; 283 slot_row = slot_w * bpp;
242 284
243 /* how many slots are can be accessed via one physical page */ 285 /* how many slots are can be accessed via one physical page */
@@ -443,8 +485,8 @@ static s32 _m_free(struct mem_info *mi)
443 } 485 }
444 kfree(mi->pg_ptr); 486 kfree(mi->pg_ptr);
445 } else if (mi->mem) { 487 } else if (mi->mem) {
446 tmm_free(TMM_SS(mi->sys_addr), mi->mem); 488 tmm_free(TMM_SS(mi->blk.phys), mi->mem);
447 clear_pat(TMM_SS(mi->sys_addr), &mi->area); 489 clear_pat(TMM_SS(mi->blk.phys), &mi->area);
448 } 490 }
449 491
450 /* safe deletion as list may not have been assigned */ 492 /* safe deletion as list may not have been assigned */
@@ -530,7 +572,7 @@ static s32 register_buf(struct __buf_info *_b, struct process_info *pi)
530 /* find each block */ 572 /* find each block */
531 list_for_each_entry(mi, &blocks, global) { 573 list_for_each_entry(mi, &blocks, global) {
532 for (i = 0; i < num; i++) { 574 for (i = 0; i < num; i++) {
533 if (!_b->mi[i] && mi->sys_addr == b->blocks[i].ssptr) { 575 if (!_b->mi[i] && mi->blk.phys == b->blocks[i].ssptr) {
534 _b->mi[i] = mi; 576 _b->mi[i] = mi;
535 577
536 /* quit if found all*/ 578 /* quit if found all*/
@@ -774,7 +816,7 @@ static struct mem_info *__get_area(enum tiler_fmt fmt, u32 width, u32 height,
774 gi->refs--; 816 gi->refs--;
775 mutex_unlock(&mtx); 817 mutex_unlock(&mtx);
776 818
777 mi->sys_addr = __get_alias_addr(fmt, mi->area.p0.x, mi->area.p0.y) 819 mi->blk.phys = __get_alias_addr(fmt, mi->area.p0.x, mi->area.p0.y)
778 + in_offs; 820 + in_offs;
779 return mi; 821 return mi;
780} 822}
@@ -783,7 +825,7 @@ static s32 tiler_mmap(struct file *filp, struct vm_area_struct *vma)
783{ 825{
784 struct __buf_info *_b = NULL; 826 struct __buf_info *_b = NULL;
785 struct tiler_buf_info *b = NULL; 827 struct tiler_buf_info *b = NULL;
786 s32 i = 0, j = 0, k = 0, m = 0, p = 0, bpp = 1; 828 s32 i = 0, j = 0, k = 0, m = 0, p = 0;
787 struct list_head *pos = NULL; 829 struct list_head *pos = NULL;
788 struct process_info *pi = filp->private_data; 830 struct process_info *pi = filp->private_data;
789 831
@@ -805,36 +847,15 @@ static s32 tiler_mmap(struct file *filp, struct vm_area_struct *vma)
805 b = &_b->buf_info; 847 b = &_b->buf_info;
806 848
807 for (i = 0; i < b->num_blocks; i++) { 849 for (i = 0; i < b->num_blocks; i++) {
808 if (b->blocks[i].fmt >= TILFMT_8BIT && 850 p = tiler_vstride(&_b->mi[i]->blk);
809 b->blocks[i].fmt <= TILFMT_32BIT) { 851 for (m = j = 0; j < _b->mi[i]->blk.height; j++) {
810 /* get line width */ 852 /* map each page of the line */
811 bpp = (b->blocks[i].fmt == TILFMT_8BIT ? 1 : 853 vma->vm_pgoff = (b->blocks[i].ssptr + m) >> PAGE_SHIFT;
812 b->blocks[i].fmt == TILFMT_16BIT ? 2 : 4);
813 p = PAGE_ALIGN(b->blocks[i].dim.area.width * bpp);
814
815 for (j = 0; j < b->blocks[i].dim.area.height; j++) {
816 /* map each page of the line */
817 vma->vm_pgoff =
818 (b->blocks[i].ssptr + m) >> PAGE_SHIFT;
819 if (remap_pfn_range(vma, vma->vm_start + k,
820 (b->blocks[i].ssptr + m) >> PAGE_SHIFT,
821 p, vma->vm_page_prot))
822 return -EAGAIN;
823 k += p;
824 if (b->blocks[i].fmt == TILFMT_8BIT)
825 m += 64*TILER_WIDTH;
826 else
827 m += 2*64*TILER_WIDTH;
828 }
829 m = 0;
830 } else if (b->blocks[i].fmt == TILFMT_PAGE) {
831 vma->vm_pgoff = (b->blocks[i].ssptr) >> PAGE_SHIFT;
832 p = PAGE_ALIGN(b->blocks[i].dim.len);
833 if (remap_pfn_range(vma, vma->vm_start + k, 854 if (remap_pfn_range(vma, vma->vm_start + k,
834 (b->blocks[i].ssptr) >> PAGE_SHIFT, p, 855 vma->vm_pgoff, p, vma->vm_page_prot))
835 vma->vm_page_prot)) 856 return -EAGAIN;
836 return -EAGAIN;;
837 k += p; 857 k += p;
858 m += tiler_pstride(&_b->mi[i]->blk);
838 } 859 }
839 } 860 }
840 return 0; 861 return 0;
@@ -874,8 +895,9 @@ static s32 refill_pat(struct tmm *tmm, struct tcm_area *area, u32 *ptr)
874 return res; 895 return res;
875} 896}
876 897
877static s32 map_block(enum tiler_fmt fmt, u32 width, u32 height, u32 gid, 898static s32 map_block(enum tiler_fmt fmt, u32 width, u32 height,
878 struct process_info *pi, u32 *sys_addr, u32 usr_addr) 899 u32 key, u32 gid, struct process_info *pi,
900 struct mem_info **info, u32 usr_addr)
879{ 901{
880 u32 i = 0, tmp = -1, *mem = NULL; 902 u32 i = 0, tmp = -1, *mem = NULL;
881 u8 write = 0; 903 u8 write = 0;
@@ -887,6 +909,8 @@ static s32 map_block(enum tiler_fmt fmt, u32 width, u32 height, u32 gid,
887 struct vm_area_struct *vma = NULL; 909 struct vm_area_struct *vma = NULL;
888 struct gid_info *gi = NULL; 910 struct gid_info *gi = NULL;
889 911
912 *info = NULL;
913
890 /* we only support mapping a user buffer in page mode */ 914 /* we only support mapping a user buffer in page mode */
891 if (fmt != TILFMT_PAGE) 915 if (fmt != TILFMT_PAGE)
892 return -EPERM; 916 return -EPERM;
@@ -913,7 +937,8 @@ static s32 map_block(enum tiler_fmt fmt, u32 width, u32 height, u32 gid,
913 return -ENOMEM; 937 return -ENOMEM;
914 } 938 }
915 939
916 *sys_addr = mi->sys_addr; 940 mi->blk.width = width;
941 mi->blk.height = height;
917 mi->usr = usr_addr; 942 mi->usr = usr_addr;
918 943
919 /* allocate pages */ 944 /* allocate pages */
@@ -979,6 +1004,7 @@ static s32 map_block(enum tiler_fmt fmt, u32 width, u32 height, u32 gid,
979 goto fault; 1004 goto fault;
980 1005
981 res = 0; 1006 res = 0;
1007 *info = mi;
982 goto done; 1008 goto done;
983fault: 1009fault:
984 up_read(&mm->mmap_sem); 1010 up_read(&mm->mmap_sem);
@@ -992,19 +1018,32 @@ done:
992 return res; 1018 return res;
993} 1019}
994 1020
995s32 tiler_mapx(enum tiler_fmt fmt, u32 width, u32 height, u32 gid, 1021s32 tiler_mapx(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 gid,
996 pid_t pid, u32 *sys_addr, u32 usr_addr) 1022 pid_t pid, u32 usr_addr)
997{ 1023{
998 return map_block(fmt, width, height, gid, __get_pi(pid, true), 1024 struct mem_info *mi;
999 sys_addr, usr_addr); 1025 struct process_info *pi;
1026 s32 res;
1027
1028 if (!blk || blk->phys)
1029 BUG();
1030
1031 pi = __get_pi(pid, true);
1032 if (!pi)
1033 return -ENOMEM;
1034
1035 res = map_block(fmt, blk->width, blk->height, blk->key, gid, pi, &mi,
1036 usr_addr);
1037 if (mi)
1038 blk->phys = mi->blk.phys;
1039 return res;
1040
1000} 1041}
1001EXPORT_SYMBOL(tiler_mapx); 1042EXPORT_SYMBOL(tiler_mapx);
1002 1043
1003s32 tiler_map(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr, 1044s32 tiler_map(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 usr_addr)
1004 u32 usr_addr)
1005{ 1045{
1006 return tiler_mapx(fmt, width, height, 0, current->tgid, sys_addr, 1046 return tiler_mapx(blk, fmt, 0, current->tgid, usr_addr);
1007 usr_addr);
1008} 1047}
1009EXPORT_SYMBOL(tiler_map); 1048EXPORT_SYMBOL(tiler_map);
1010 1049
@@ -1022,7 +1061,7 @@ s32 free_block(u32 sys_addr, struct process_info *pi)
1022 /* currently we know if block is 1D or 2D by the address */ 1061 /* currently we know if block is 1D or 2D by the address */
1023 if (TILER_GET_ACC_MODE(sys_addr) == TILFMT_PAGE) { 1062 if (TILER_GET_ACC_MODE(sys_addr) == TILFMT_PAGE) {
1024 list_for_each_entry(mi, &gi->onedim, by_area) { 1063 list_for_each_entry(mi, &gi->onedim, by_area) {
1025 if (mi->sys_addr == sys_addr) { 1064 if (mi->blk.phys == sys_addr) {
1026 _m_try_free(mi); 1065 _m_try_free(mi);
1027 res = 0; 1066 res = 0;
1028 goto done; 1067 goto done;
@@ -1031,7 +1070,7 @@ s32 free_block(u32 sys_addr, struct process_info *pi)
1031 } else { 1070 } else {
1032 list_for_each_entry(ai, &gi->areas, by_gid) { 1071 list_for_each_entry(ai, &gi->areas, by_gid) {
1033 list_for_each_entry(mi, &ai->blocks, by_area) { 1072 list_for_each_entry(mi, &ai->blocks, by_area) {
1034 if (mi->sys_addr == sys_addr) { 1073 if (mi->blk.phys == sys_addr) {
1035 _m_try_free(mi); 1074 _m_try_free(mi);
1036 res = 0; 1075 res = 0;
1037 goto done; 1076 goto done;
@@ -1048,7 +1087,28 @@ done:
1048 return res; 1087 return res;
1049} 1088}
1050 1089
1051s32 tiler_free(u32 sys_addr) 1090s32 free_block_global(u32 ssptr)
1091{
1092 struct mem_info *mi;
1093 s32 res = -ENOENT;
1094
1095 mutex_lock(&mtx);
1096
1097 /* find block in global list and free it */
1098 list_for_each_entry(mi, &blocks, global) {
1099 if (mi->blk.phys == ssptr) {
1100 _m_try_free(mi);
1101 res = 0;
1102 break;
1103 }
1104 }
1105 mutex_unlock(&mtx);
1106
1107 /* for debugging, we can set the PAT entries to DMM_LISA_MAP__0 */
1108 return res;
1109}
1110
1111s32 tiler_free(struct tiler_block_t *blk)
1052{ 1112{
1053 struct mem_info *mi; 1113 struct mem_info *mi;
1054 s32 res = -ENOENT; 1114 s32 res = -ENOENT;
@@ -1057,7 +1117,7 @@ s32 tiler_free(u32 sys_addr)
1057 1117
1058 /* find block in global list and free it */ 1118 /* find block in global list and free it */
1059 list_for_each_entry(mi, &blocks, global) { 1119 list_for_each_entry(mi, &blocks, global) {
1060 if (mi->sys_addr == sys_addr) { 1120 if (mi->blk.phys == blk->phys) {
1061 _m_try_free(mi); 1121 _m_try_free(mi);
1062 res = 0; 1122 res = 0;
1063 break; 1123 break;
@@ -1070,54 +1130,47 @@ s32 tiler_free(u32 sys_addr)
1070} 1130}
1071EXPORT_SYMBOL(tiler_free); 1131EXPORT_SYMBOL(tiler_free);
1072 1132
1073/* :TODO: Currently we do not track enough information from alloc to get back
1074 the actual width and height of the container, so we must make a guess. We
1075 do not even have enough information to get the virtual stride of the buffer,
1076 which is the real reason for this ioctl */
1077s32 find_block(u32 sys_addr, struct tiler_block_info *blk) 1133s32 find_block(u32 sys_addr, struct tiler_block_info *blk)
1078{ 1134{
1079 struct mem_info *i; 1135 struct mem_info *i;
1080 struct tcm_pt pt; 1136 struct tcm_pt pt;
1081 1137
1138 if (!is_tiler_addr(sys_addr))
1139 return -EFAULT;
1140
1082 if (get_area(sys_addr, &pt)) 1141 if (get_area(sys_addr, &pt))
1083 return -EFAULT; 1142 return -EFAULT;
1084 1143
1085 list_for_each_entry(i, &blocks, global) { 1144 list_for_each_entry(i, &blocks, global) {
1086 if (tcm_is_in(pt, i->area)) 1145 if (tiler_fmt(&i->blk) == TILER_GET_ACC_MODE(sys_addr) &&
1146 tcm_is_in(pt, i->area))
1087 goto found; 1147 goto found;
1088 } 1148 }
1089
1090 blk->fmt = TILFMT_INVALID;
1091 blk->dim.len = blk->stride = blk->ssptr = 0;
1092 return -EFAULT; 1149 return -EFAULT;
1093 1150
1094found: 1151found:
1095 blk->ptr = NULL; 1152 blk->ptr = NULL;
1096 blk->fmt = TILER_GET_ACC_MODE(sys_addr); 1153 blk->fmt = TILER_GET_ACC_MODE(i->blk.phys);
1097 blk->ssptr = __get_alias_addr(blk->fmt, i->area.p0.x, i->area.p0.y); 1154 blk->ssptr = i->blk.phys;
1098 1155
1099 if (blk->fmt == TILFMT_PAGE) { 1156 if (blk->fmt == TILFMT_PAGE) {
1100 blk->dim.len = tcm_sizeof(i->area) * TILER_PAGE; 1157 blk->dim.len = i->blk.width;
1101 blk->stride = 0; 1158 blk->stride = 0;
1159 blk->group_id = ((struct gid_info *) i->parent)->gid;
1102 } else { 1160 } else {
1103 blk->stride = blk->dim.area.width = 1161 blk->stride = tiler_vstride(&i->blk);
1104 tcm_awidth(i->area) * TILER_BLOCK_WIDTH; 1162 blk->dim.area.width = i->blk.width;
1105 blk->dim.area.height = tcm_aheight(i->area) 1163 blk->dim.area.height = i->blk.height;
1106 * TILER_BLOCK_HEIGHT; 1164 blk->group_id = ((struct area_info *) i->parent)->gi->gid;
1107 if (blk->fmt != TILFMT_8BIT) {
1108 blk->stride <<= 1;
1109 blk->dim.area.height >>= 1;
1110 if (blk->fmt == TILFMT_32BIT)
1111 blk->dim.area.width >>= 1;
1112 }
1113 blk->stride = PAGE_ALIGN(blk->stride);
1114 } 1165 }
1166 blk->offs = i->blk.phys & ~PAGE_MASK;
1167 blk->align = 0;
1115 return 0; 1168 return 0;
1116} 1169}
1117 1170
1118static s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height, 1171static s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height,
1119 u32 align, u32 offs, u32 gid, struct process_info *pi, 1172 u32 align, u32 offs, u32 key, u32 gid, struct process_info *pi,
1120 u32 *sys_addr); 1173 struct mem_info **info);
1121 1174
1122static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd, 1175static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
1123 unsigned long arg) 1176 unsigned long arg)
@@ -1126,12 +1179,12 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
1126 pmd_t *pmd = NULL; 1179 pmd_t *pmd = NULL;
1127 pte_t *ptep = NULL, pte = 0x0; 1180 pte_t *ptep = NULL, pte = 0x0;
1128 s32 r = -1; 1181 s32 r = -1;
1129 u32 til_addr = 0x0;
1130 struct process_info *pi = filp->private_data; 1182 struct process_info *pi = filp->private_data;
1131 1183
1132 struct __buf_info *_b = NULL; 1184 struct __buf_info *_b = NULL;
1133 struct tiler_buf_info buf_info = {0}; 1185 struct tiler_buf_info buf_info = {0};
1134 struct tiler_block_info block_info = {0}; 1186 struct tiler_block_info block_info = {0};
1187 struct mem_info *mi;
1135 1188
1136 switch (cmd) { 1189 switch (cmd) {
1137 case TILIOC_GBLK: 1190 case TILIOC_GBLK:
@@ -1142,7 +1195,9 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
1142 switch (block_info.fmt) { 1195 switch (block_info.fmt) {
1143 case TILFMT_PAGE: 1196 case TILFMT_PAGE:
1144 r = alloc_block(block_info.fmt, block_info.dim.len, 1, 1197 r = alloc_block(block_info.fmt, block_info.dim.len, 1,
1145 0, 0, 0, pi, &til_addr); 1198 block_info.align, block_info.offs,
1199 block_info.key, block_info.group_id,
1200 pi, &mi);
1146 if (r) 1201 if (r)
1147 return r; 1202 return r;
1148 break; 1203 break;
@@ -1152,7 +1207,9 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
1152 r = alloc_block(block_info.fmt, 1207 r = alloc_block(block_info.fmt,
1153 block_info.dim.area.width, 1208 block_info.dim.area.width,
1154 block_info.dim.area.height, 1209 block_info.dim.area.height,
1155 0, 0, 0, pi, &til_addr); 1210 block_info.align, block_info.offs,
1211 block_info.key, block_info.group_id,
1212 pi, &mi);
1156 if (r) 1213 if (r)
1157 return r; 1214 return r;
1158 break; 1215 break;
@@ -1160,7 +1217,10 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
1160 return -EINVAL; 1217 return -EINVAL;
1161 } 1218 }
1162 1219
1163 block_info.ssptr = til_addr; 1220 if (mi) {
1221 block_info.stride = tiler_vstride(&mi->blk);
1222 block_info.ssptr = mi->blk.phys;
1223 }
1164 if (copy_to_user((void __user *)arg, &block_info, 1224 if (copy_to_user((void __user *)arg, &block_info,
1165 sizeof(block_info))) 1225 sizeof(block_info)))
1166 return -EFAULT; 1226 return -EFAULT;
@@ -1173,7 +1233,7 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
1173 1233
1174 /* search current process first, then all processes */ 1234 /* search current process first, then all processes */
1175 free_block(block_info.ssptr, pi) ? 1235 free_block(block_info.ssptr, pi) ?
1176 tiler_free(block_info.ssptr) : 0; 1236 free_block_global(block_info.ssptr) : 0;
1177 1237
1178 /* free always succeeds */ 1238 /* free always succeeds */
1179 break; 1239 break;
@@ -1203,10 +1263,16 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
1203 if (!block_info.ptr) 1263 if (!block_info.ptr)
1204 return -EFAULT; 1264 return -EFAULT;
1205 1265
1206 if (map_block(block_info.fmt, block_info.dim.len, 1, 0, pi, 1266 r = map_block(block_info.fmt, block_info.dim.len, 1,
1207 &block_info.ssptr, (u32)block_info.ptr)) 1267 block_info.key, block_info.group_id, pi,
1208 return -ENOMEM; 1268 &mi, (u32)block_info.ptr);
1269 if (r)
1270 return r;
1209 1271
1272 if (mi) {
1273 block_info.stride = tiler_vstride(&mi->blk);
1274 block_info.ssptr = mi->blk.phys;
1275 }
1210 if (copy_to_user((void __user *)arg, &block_info, 1276 if (copy_to_user((void __user *)arg, &block_info,
1211 sizeof(block_info))) 1277 sizeof(block_info)))
1212 return -EFAULT; 1278 return -EFAULT;
@@ -1292,12 +1358,14 @@ static s32 tiler_ioctl(struct inode *ip, struct file *filp, u32 cmd,
1292} 1358}
1293 1359
1294s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height, 1360s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height,
1295 u32 align, u32 offs, u32 gid, struct process_info *pi, 1361 u32 align, u32 offs, u32 key, u32 gid, struct process_info *pi,
1296 u32 *sys_addr) 1362 struct mem_info **info)
1297{ 1363{
1298 struct mem_info *mi = NULL; 1364 struct mem_info *mi = NULL;
1299 struct gid_info *gi = NULL; 1365 struct gid_info *gi = NULL;
1300 1366
1367 *info = NULL;
1368
1301 /* only support up to page alignment */ 1369 /* only support up to page alignment */
1302 if (align > PAGE_SIZE || offs > align || !pi) 1370 if (align > PAGE_SIZE || offs > align || !pi)
1303 return -EINVAL; 1371 return -EINVAL;
@@ -1320,7 +1388,8 @@ s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height,
1320 return -ENOMEM; 1388 return -ENOMEM;
1321 } 1389 }
1322 1390
1323 *sys_addr = mi->sys_addr; 1391 mi->blk.width = width;
1392 mi->blk.height = height;
1324 1393
1325 /* allocate and map if mapping is supported */ 1394 /* allocate and map if mapping is supported */
1326 if (tmm_can_map(TMM(fmt))) { 1395 if (tmm_can_map(TMM(fmt))) {
@@ -1334,6 +1403,7 @@ s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height,
1334 if (refill_pat(TMM(fmt), &mi->area, mi->mem)) 1403 if (refill_pat(TMM(fmt), &mi->area, mi->mem))
1335 goto cleanup; 1404 goto cleanup;
1336 } 1405 }
1406 *info = mi;
1337 return 0; 1407 return 0;
1338 1408
1339cleanup: 1409cleanup:
@@ -1344,22 +1414,35 @@ cleanup:
1344 1414
1345} 1415}
1346 1416
1347s32 tiler_allocx(enum tiler_fmt fmt, u32 width, u32 height, 1417s32 tiler_allocx(struct tiler_block_t *blk, enum tiler_fmt fmt,
1348 u32 align, u32 offs, u32 gid, pid_t pid, u32 *sys_addr) 1418 u32 align, u32 offs, u32 gid, pid_t pid)
1349{ 1419{
1350 return alloc_block(fmt, width, height, align, offs, gid, 1420 struct mem_info *mi;
1351 __get_pi(pid, true), sys_addr); 1421 struct process_info *pi;
1422 s32 res;
1423
1424 if (!blk || blk->phys)
1425 BUG();
1426
1427 pi = __get_pi(pid, true);
1428 if (!pi)
1429 return -ENOMEM;
1430
1431 res = alloc_block(fmt, blk->width, blk->height, align, offs, blk->key,
1432 gid, pi, &mi);
1433 if (mi)
1434 blk->phys = mi->blk.phys;
1435 return res;
1352} 1436}
1353EXPORT_SYMBOL(tiler_allocx); 1437EXPORT_SYMBOL(tiler_allocx);
1354 1438
1355s32 tiler_alloc(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr) 1439s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt,
1440 u32 align, u32 offs)
1356{ 1441{
1357 return tiler_allocx(fmt, width, height, 0, 0, 1442 return tiler_allocx(blk, fmt, align, offs, 0, current->tgid);
1358 0, current->tgid, sys_addr);
1359} 1443}
1360EXPORT_SYMBOL(tiler_alloc); 1444EXPORT_SYMBOL(tiler_alloc);
1361 1445
1362
1363static void reserve_nv12_blocks(u32 n, u32 width, u32 height, 1446static void reserve_nv12_blocks(u32 n, u32 width, u32 height,
1364 u32 align, u32 offs, u32 gid, pid_t pid) 1447 u32 align, u32 offs, u32 gid, pid_t pid)
1365{ 1448{
diff --git a/drivers/media/video/tiler/tiler_def.h b/drivers/media/video/tiler/tiler_def.h
index 61212295ebb..d931e18de15 100644
--- a/drivers/media/video/tiler/tiler_def.h
+++ b/drivers/media/video/tiler/tiler_def.h
@@ -28,7 +28,13 @@
28#define TILER_GET_ACC_MODE(x) ((enum tiler_fmt) (TILFMT_8BIT + \ 28#define TILER_GET_ACC_MODE(x) ((enum tiler_fmt) (TILFMT_8BIT + \
29(((u32)x & (TILER_ACC_MODE_MASK<<TILER_ACC_MODE_SHIFT))>>TILER_ACC_MODE_SHIFT))) 29(((u32)x & (TILER_ACC_MODE_MASK<<TILER_ACC_MODE_SHIFT))>>TILER_ACC_MODE_SHIFT)))
30 30
31#define TILER_ALIAS_BASE (0x60000000) 31#define TILER_ALIAS_BASE 0x60000000u
32#define TILVIEW_8BIT TILER_ALIAS_BASE
33#define TILVIEW_16BIT (TILVIEW_8BIT + 0x08000000u)
34#define TILVIEW_32BIT (TILVIEW_16BIT + 0x08000000u)
35#define TILVIEW_PAGE (TILVIEW_32BIT + 0x08000000u)
36#define TILVIEW_END (TILVIEW_PAGE + 0x08000000u)
37
32#define TILER_ACC_MODE_SHIFT (27) 38#define TILER_ACC_MODE_SHIFT (27)
33#define DMM_ACC_MODE_SHIFT (27) 39#define DMM_ACC_MODE_SHIFT (27)
34 40