20 #include <linux/slab.h>
25 #define ALIGN_DOWN(value, align) ((value) & ~((align) - 1))
38 static void sita_deinit(
struct tcm *
tcm);
68 static void get_neighbor_stats(
struct tcm *
tcm,
struct tcm_area *area,
71 static void fill_area(
struct tcm *
tcm,
87 if (width == 0 || height == 0)
95 memset(tcm, 0,
sizeof(*tcm));
96 memset(pvt, 0,
sizeof(*pvt));
103 tcm->
free = sita_free;
104 tcm->
deinit = sita_deinit;
105 tcm->
pvt = (
void *)pvt;
114 for (i = 0; i < tcm->
width; i++) {
126 if (attr && attr->
x <= tcm->
width && attr->
y <= tcm->
height) {
137 spin_lock(&(pvt->
lock));
138 assign(&area, 0, 0, width - 1, height - 1);
139 fill_area(tcm, &area,
NULL);
140 spin_unlock(&(pvt->
lock));
149 static void sita_deinit(
struct tcm *
tcm)
158 spin_lock(&(pvt->lock));
160 spin_unlock(&(pvt->lock));
184 spin_lock(&(pvt->
lock));
187 assign(&field, tcm->
width - 1, tcm->
height - 1, 0, 0);
189 ret = scan_r2l_b2t_one_dim(tcm, num_slots, &field, area);
192 fill_area(tcm, area, area);
194 spin_unlock(&(pvt->
lock));
219 align = align <= 1 ? 1 : align <= 32 ? 32 : 64;
221 spin_lock(&(pvt->
lock));
222 ret = scan_areas_and_find_fit(tcm, w, h, align, area);
225 fill_area(tcm, area, area);
227 spin_unlock(&(pvt->
lock));
236 static s32 sita_free(
struct tcm *tcm,
struct tcm_area *area)
240 spin_lock(&(pvt->
lock));
244 pvt->
map[area->
p1.x][area->
p1.y] != area);
247 fill_area(tcm, area,
NULL);
249 spin_unlock(&(pvt->
lock));
274 static s32 scan_r2l_t2b(
struct tcm *tcm,
u16 w,
u16 h,
u16 align,
278 s16 start_x, end_x, start_y, end_y, found_x = -1;
280 struct score best = {{0}, {0}, {0}, 0};
282 start_x = field->
p0.x;
284 start_y = field->
p0.y;
288 if (field->
p0.x < field->
p1.x ||
289 field->
p1.y < field->
p0.y)
293 if (w >
LEN(start_x, end_x) || h >
LEN(end_y, start_y))
298 end_y = end_y - h + 1;
305 for (y = start_y; y <= end_y; y++) {
306 for (x = start_x; x >= end_x; x -=
align) {
307 if (is_area_free(map, x, y, w, h)) {
311 if (update_candidate(tcm, x, y, w, h, field,
318 }
else if (map[x][y] && map[x][y]->is2d) {
320 x =
ALIGN(map[x][y]->
p0.x - w + 1, align);
325 if (found_x == start_x)
332 assign(area, best.
a.p0.x, best.
a.p0.y, best.
a.p1.x, best.
a.p1.y);
348 static s32 scan_l2r_t2b(
struct tcm *tcm,
u16 w,
u16 h,
u16 align,
352 s16 start_x, end_x, start_y, end_y, found_x = -1;
354 struct score best = {{0}, {0}, {0}, 0};
356 start_x = field->
p0.x;
358 start_y = field->
p0.y;
362 if (field->
p1.x < field->
p0.x ||
363 field->
p1.y < field->
p0.y)
367 if (w >
LEN(end_x, start_x) || h >
LEN(end_y, start_y))
370 start_x =
ALIGN(start_x, align);
373 if (w >
LEN(end_x, start_x))
377 end_x = end_x - w + 1;
378 end_y = end_y - h + 1;
381 for (y = start_y; y <= end_y; y++) {
382 for (x = start_x; x <= end_x; x +=
align) {
383 if (is_area_free(map, x, y, w, h)) {
387 if (update_candidate(tcm, x, y, w, h, field,
394 }
else if (map[x][y] && map[x][y]->is2d) {
401 if (found_x == start_x)
408 assign(area, best.
a.p0.x, best.
a.p0.y, best.
a.p1.x, best.
a.p1.y);
424 static s32 scan_r2l_b2t_one_dim(
struct tcm *tcm,
u32 num_slots,
433 if (field->
p0.y < field->
p1.y)
440 if (tcm->
width != field->
p0.x - field->
p1.x + 1)
444 if (num_slots > tcm->
width *
LEN(field->
p0.y, field->
p1.y))
451 while (found < num_slots) {
474 if (found == num_slots)
481 x = (x ? : tcm->
width) - 1;
502 static s32 scan_areas_and_find_fit(
struct tcm *tcm,
u16 w,
u16 h,
u16 align,
507 u16 boundary_x, boundary_y;
512 boundary_x = pvt->
div_pt.x - 1;
513 boundary_y = pvt->
div_pt.y - 1;
517 boundary_x = tcm->
width - 1;
519 boundary_y = tcm->
height - 1;
521 assign(&field, 0, 0, boundary_x, boundary_y);
522 ret = scan_l2r_t2b(tcm, w, h, align, &field, area);
525 if (ret != 0 && (boundary_x != tcm->
width - 1 ||
526 boundary_y != tcm->
height - 1)) {
528 assign(&field, 0, 0, tcm->
width - 1, tcm->
height - 1);
529 ret = scan_l2r_t2b(tcm, w, h, align, &field, area);
531 }
else if (align == 1) {
533 boundary_x = pvt->
div_pt.x;
534 boundary_y = pvt->
div_pt.y - 1;
540 boundary_y = tcm->
height - 1;
542 assign(&field, tcm->
width - 1, 0, boundary_x, boundary_y);
543 ret = scan_r2l_t2b(tcm, w, h, align, &field, area);
546 if (ret != 0 && (boundary_x != 0 ||
547 boundary_y != tcm->
height - 1)) {
549 assign(&field, tcm->
width - 1, 0, 0, tcm->
height - 1);
550 ret = scan_r2l_t2b(tcm, w, h, align, &field,
562 for (y = y0; y < y0 +
h; y++) {
563 for (x = x0; x < x0 +
w; x++) {
572 static void fill_area(
struct tcm *tcm,
struct tcm_area *area,
583 for (x = a.
p0.x; x <= a.
p1.x; ++x)
584 for (y = a.
p0.y; y <= a.
p1.y; ++y)
585 pvt->
map[
x][
y] = parent;
602 static s32 update_candidate(
struct tcm *tcm,
u16 x0,
u16 y0,
u16 w,
u16 h,
615 assign(&me.a, x0, y0, x0 + w - 1, y0 + h - 1);
619 get_neighbor_stats(tcm, &me.a, &me.n);
620 me.neighs = me.n.edge + me.n.busy;
621 get_nearness_factor(field, &me.a, &me.f);
632 best->
neighs <= me.neighs &&
633 (best->
neighs < me.neighs ||
635 best->
n.busy < me.n.busy ||
636 (best->
n.busy == me.n.busy &&
638 best->
f.x + best->
f.y > me.f.x + me.f.y)))
646 memcpy(best, &me,
sizeof(me));
655 static void get_nearness_factor(
struct tcm_area *field,
struct tcm_area *area,
662 nf->
x = (
s32)(area->
p0.x - field->
p0.x) * 1000 /
663 (field->
p1.x - field->
p0.x);
664 nf->
y = (
s32)(area->
p0.y - field->
p0.y) * 1000 /
665 (field->
p1.y - field->
p0.y);
669 static void get_neighbor_stats(
struct tcm *tcm,
struct tcm_area *area,
676 memset(stat, 0,
sizeof(*stat));
679 for (x = area->
p0.x; x <= area->
p1.x; x++) {
682 else if (pvt->
map[x][area->
p0.y - 1])
687 else if (pvt->
map[x][area->
p1.y + 1])
692 for (y = area->
p0.y; y <= area->
p1.y; ++y) {
695 else if (pvt->
map[area->
p0.x - 1][y])
698 if (area->
p1.x == tcm->
width - 1)
700 else if (pvt->
map[area->
p1.x + 1][y])