tcm-sita.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /*
  2. * tcm-sita.c
  3. *
  4. * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation) algorithm
  5. *
  6. * Authors: Ravi Ramachandra <r.ramachandra@ti.com>,
  7. * Lajos Molnar <molnar@ti.com>
  8. *
  9. * Copyright (C) 2009-2010 Texas Instruments, Inc.
  10. *
  11. * This package is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2 as
  13. * published by the Free Software Foundation.
  14. *
  15. * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17. * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18. *
  19. */
  20. #include <linux/slab.h>
  21. #include <linux/spinlock.h>
  22. #include "tcm-sita.h"
  23. #define ALIGN_DOWN(value, align) ((value) & ~((align) - 1))
  24. /* Individual selection criteria for different scan areas */
  25. static s32 CR_L2R_T2B = CR_BIAS_HORIZONTAL;
  26. static s32 CR_R2L_T2B = CR_DIAGONAL_BALANCE;
  27. /*********************************************
  28. * TCM API - Sita Implementation
  29. *********************************************/
  30. static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
  31. struct tcm_area *area);
  32. static s32 sita_reserve_1d(struct tcm *tcm, u32 slots, struct tcm_area *area);
  33. static s32 sita_free(struct tcm *tcm, struct tcm_area *area);
  34. static void sita_deinit(struct tcm *tcm);
  35. /*********************************************
  36. * Main Scanner functions
  37. *********************************************/
  38. static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
  39. struct tcm_area *area);
  40. static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
  41. struct tcm_area *field, struct tcm_area *area);
  42. static s32 scan_r2l_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
  43. struct tcm_area *field, struct tcm_area *area);
  44. static s32 scan_r2l_b2t_one_dim(struct tcm *tcm, u32 num_slots,
  45. struct tcm_area *field, struct tcm_area *area);
  46. /*********************************************
  47. * Support Infrastructure Methods
  48. *********************************************/
  49. static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h);
  50. static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
  51. struct tcm_area *field, s32 criteria,
  52. struct score *best);
  53. static void get_nearness_factor(struct tcm_area *field,
  54. struct tcm_area *candidate,
  55. struct nearness_factor *nf);
  56. static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
  57. struct neighbor_stats *stat);
  58. static void fill_area(struct tcm *tcm,
  59. struct tcm_area *area, struct tcm_area *parent);
  60. /*********************************************/
  61. /*********************************************
  62. * Utility Methods
  63. *********************************************/
  64. struct tcm *sita_init(u16 width, u16 height, struct tcm_pt *attr)
  65. {
  66. struct tcm *tcm;
  67. struct sita_pvt *pvt;
  68. struct tcm_area area = {0};
  69. s32 i;
  70. if (width == 0 || height == 0)
  71. return NULL;
  72. tcm = kmalloc(sizeof(*tcm), GFP_KERNEL);
  73. pvt = kmalloc(sizeof(*pvt), GFP_KERNEL);
  74. if (!tcm || !pvt)
  75. goto error;
  76. memset(tcm, 0, sizeof(*tcm));
  77. memset(pvt, 0, sizeof(*pvt));
  78. /* Updating the pointers to SiTA implementation APIs */
  79. tcm->height = height;
  80. tcm->width = width;
  81. tcm->reserve_2d = sita_reserve_2d;
  82. tcm->reserve_1d = sita_reserve_1d;
  83. tcm->free = sita_free;
  84. tcm->deinit = sita_deinit;
  85. tcm->pvt = (void *)pvt;
  86. spin_lock_init(&(pvt->lock));
  87. /* Creating tam map */
  88. pvt->map = kmalloc(sizeof(*pvt->map) * tcm->width, GFP_KERNEL);
  89. if (!pvt->map)
  90. goto error;
  91. for (i = 0; i < tcm->width; i++) {
  92. pvt->map[i] =
  93. kmalloc(sizeof(**pvt->map) * tcm->height,
  94. GFP_KERNEL);
  95. if (pvt->map[i] == NULL) {
  96. while (i--)
  97. kfree(pvt->map[i]);
  98. kfree(pvt->map);
  99. goto error;
  100. }
  101. }
  102. if (attr && attr->x <= tcm->width && attr->y <= tcm->height) {
  103. pvt->div_pt.x = attr->x;
  104. pvt->div_pt.y = attr->y;
  105. } else {
  106. /* Defaulting to 3:1 ratio on width for 2D area split */
  107. /* Defaulting to 3:1 ratio on height for 2D and 1D split */
  108. pvt->div_pt.x = (tcm->width * 3) / 4;
  109. pvt->div_pt.y = (tcm->height * 3) / 4;
  110. }
  111. spin_lock(&(pvt->lock));
  112. assign(&area, 0, 0, width - 1, height - 1);
  113. fill_area(tcm, &area, NULL);
  114. spin_unlock(&(pvt->lock));
  115. return tcm;
  116. error:
  117. kfree(tcm);
  118. kfree(pvt);
  119. return NULL;
  120. }
  121. static void sita_deinit(struct tcm *tcm)
  122. {
  123. struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
  124. struct tcm_area area = {0};
  125. s32 i;
  126. area.p1.x = tcm->width - 1;
  127. area.p1.y = tcm->height - 1;
  128. spin_lock(&(pvt->lock));
  129. fill_area(tcm, &area, NULL);
  130. spin_unlock(&(pvt->lock));
  131. for (i = 0; i < tcm->height; i++)
  132. kfree(pvt->map[i]);
  133. kfree(pvt->map);
  134. kfree(pvt);
  135. }
  136. /**
  137. * Reserve a 1D area in the container
  138. *
  139. * @param num_slots size of 1D area
  140. * @param area pointer to the area that will be populated with the
  141. * reserved area
  142. *
  143. * @return 0 on success, non-0 error value on failure.
  144. */
  145. static s32 sita_reserve_1d(struct tcm *tcm, u32 num_slots,
  146. struct tcm_area *area)
  147. {
  148. s32 ret;
  149. struct tcm_area field = {0};
  150. struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
  151. spin_lock(&(pvt->lock));
  152. /* Scanning entire container */
  153. assign(&field, tcm->width - 1, tcm->height - 1, 0, 0);
  154. ret = scan_r2l_b2t_one_dim(tcm, num_slots, &field, area);
  155. if (!ret)
  156. /* update map */
  157. fill_area(tcm, area, area);
  158. spin_unlock(&(pvt->lock));
  159. return ret;
  160. }
  161. /**
  162. * Reserve a 2D area in the container
  163. *
  164. * @param w width
  165. * @param h height
  166. * @param area pointer to the area that will be populated with the reserved
  167. * area
  168. *
  169. * @return 0 on success, non-0 error value on failure.
  170. */
  171. static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
  172. struct tcm_area *area)
  173. {
  174. s32 ret;
  175. struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
  176. /* not supporting more than 64 as alignment */
  177. if (align > 64)
  178. return -EINVAL;
  179. /* we prefer 1, 32 and 64 as alignment */
  180. align = align <= 1 ? 1 : align <= 32 ? 32 : 64;
  181. spin_lock(&(pvt->lock));
  182. ret = scan_areas_and_find_fit(tcm, w, h, align, area);
  183. if (!ret)
  184. /* update map */
  185. fill_area(tcm, area, area);
  186. spin_unlock(&(pvt->lock));
  187. return ret;
  188. }
  189. /**
  190. * Unreserve a previously allocated 2D or 1D area
  191. * @param area area to be freed
  192. * @return 0 - success
  193. */
  194. static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
  195. {
  196. struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
  197. spin_lock(&(pvt->lock));
  198. /* check that this is in fact an existing area */
  199. WARN_ON(pvt->map[area->p0.x][area->p0.y] != area ||
  200. pvt->map[area->p1.x][area->p1.y] != area);
  201. /* Clear the contents of the associated tiles in the map */
  202. fill_area(tcm, area, NULL);
  203. spin_unlock(&(pvt->lock));
  204. return 0;
  205. }
  206. /**
  207. * Note: In general the cordinates in the scan field area relevant to the can
  208. * sweep directions. The scan origin (e.g. top-left corner) will always be
  209. * the p0 member of the field. Therfore, for a scan from top-left p0.x <= p1.x
  210. * and p0.y <= p1.y; whereas, for a scan from bottom-right p1.x <= p0.x and p1.y
  211. * <= p0.y
  212. */
  213. /**
  214. * Raster scan horizontally right to left from top to bottom to find a place for
  215. * a 2D area of given size inside a scan field.
  216. *
  217. * @param w width of desired area
  218. * @param h height of desired area
  219. * @param align desired area alignment
  220. * @param area pointer to the area that will be set to the best position
  221. * @param field area to scan (inclusive)
  222. *
  223. * @return 0 on success, non-0 error value on failure.
  224. */
  225. static s32 scan_r2l_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
  226. struct tcm_area *field, struct tcm_area *area)
  227. {
  228. s32 x, y;
  229. s16 start_x, end_x, start_y, end_y, found_x = -1;
  230. struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
  231. struct score best = {{0}, {0}, {0}, 0};
  232. start_x = field->p0.x;
  233. end_x = field->p1.x;
  234. start_y = field->p0.y;
  235. end_y = field->p1.y;
  236. /* check scan area co-ordinates */
  237. if (field->p0.x < field->p1.x ||
  238. field->p1.y < field->p0.y)
  239. return -EINVAL;
  240. /* check if allocation would fit in scan area */
  241. if (w > LEN(start_x, end_x) || h > LEN(end_y, start_y))
  242. return -ENOSPC;
  243. /* adjust start_x and end_y, as allocation would not fit beyond */
  244. start_x = ALIGN_DOWN(start_x - w + 1, align); /* - 1 to be inclusive */
  245. end_y = end_y - h + 1;
  246. /* check if allocation would still fit in scan area */
  247. if (start_x < end_x)
  248. return -ENOSPC;
  249. /* scan field top-to-bottom, right-to-left */
  250. for (y = start_y; y <= end_y; y++) {
  251. for (x = start_x; x >= end_x; x -= align) {
  252. if (is_area_free(map, x, y, w, h)) {
  253. found_x = x;
  254. /* update best candidate */
  255. if (update_candidate(tcm, x, y, w, h, field,
  256. CR_R2L_T2B, &best))
  257. goto done;
  258. /* change upper x bound */
  259. end_x = x + 1;
  260. break;
  261. } else if (map[x][y] && map[x][y]->is2d) {
  262. /* step over 2D areas */
  263. x = ALIGN(map[x][y]->p0.x - w + 1, align);
  264. }
  265. }
  266. /* break if you find a free area shouldering the scan field */
  267. if (found_x == start_x)
  268. break;
  269. }
  270. if (!best.a.tcm)
  271. return -ENOSPC;
  272. done:
  273. assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
  274. return 0;
  275. }
  276. /**
  277. * Raster scan horizontally left to right from top to bottom to find a place for
  278. * a 2D area of given size inside a scan field.
  279. *
  280. * @param w width of desired area
  281. * @param h height of desired area
  282. * @param align desired area alignment
  283. * @param area pointer to the area that will be set to the best position
  284. * @param field area to scan (inclusive)
  285. *
  286. * @return 0 on success, non-0 error value on failure.
  287. */
  288. static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
  289. struct tcm_area *field, struct tcm_area *area)
  290. {
  291. s32 x, y;
  292. s16 start_x, end_x, start_y, end_y, found_x = -1;
  293. struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
  294. struct score best = {{0}, {0}, {0}, 0};
  295. start_x = field->p0.x;
  296. end_x = field->p1.x;
  297. start_y = field->p0.y;
  298. end_y = field->p1.y;
  299. /* check scan area co-ordinates */
  300. if (field->p1.x < field->p0.x ||
  301. field->p1.y < field->p0.y)
  302. return -EINVAL;
  303. /* check if allocation would fit in scan area */
  304. if (w > LEN(end_x, start_x) || h > LEN(end_y, start_y))
  305. return -ENOSPC;
  306. start_x = ALIGN(start_x, align);
  307. /* check if allocation would still fit in scan area */
  308. if (w > LEN(end_x, start_x))
  309. return -ENOSPC;
  310. /* adjust end_x and end_y, as allocation would not fit beyond */
  311. end_x = end_x - w + 1; /* + 1 to be inclusive */
  312. end_y = end_y - h + 1;
  313. /* scan field top-to-bottom, left-to-right */
  314. for (y = start_y; y <= end_y; y++) {
  315. for (x = start_x; x <= end_x; x += align) {
  316. if (is_area_free(map, x, y, w, h)) {
  317. found_x = x;
  318. /* update best candidate */
  319. if (update_candidate(tcm, x, y, w, h, field,
  320. CR_L2R_T2B, &best))
  321. goto done;
  322. /* change upper x bound */
  323. end_x = x - 1;
  324. break;
  325. } else if (map[x][y] && map[x][y]->is2d) {
  326. /* step over 2D areas */
  327. x = ALIGN_DOWN(map[x][y]->p1.x, align);
  328. }
  329. }
  330. /* break if you find a free area shouldering the scan field */
  331. if (found_x == start_x)
  332. break;
  333. }
  334. if (!best.a.tcm)
  335. return -ENOSPC;
  336. done:
  337. assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
  338. return 0;
  339. }
  340. /**
  341. * Raster scan horizontally right to left from bottom to top to find a place
  342. * for a 1D area of given size inside a scan field.
  343. *
  344. * @param num_slots size of desired area
  345. * @param align desired area alignment
  346. * @param area pointer to the area that will be set to the best
  347. * position
  348. * @param field area to scan (inclusive)
  349. *
  350. * @return 0 on success, non-0 error value on failure.
  351. */
  352. static s32 scan_r2l_b2t_one_dim(struct tcm *tcm, u32 num_slots,
  353. struct tcm_area *field, struct tcm_area *area)
  354. {
  355. s32 found = 0;
  356. s16 x, y;
  357. struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
  358. struct tcm_area *p;
  359. /* check scan area co-ordinates */
  360. if (field->p0.y < field->p1.y)
  361. return -EINVAL;
  362. /**
  363. * Currently we only support full width 1D scan field, which makes sense
  364. * since 1D slot-ordering spans the full container width.
  365. */
  366. if (tcm->width != field->p0.x - field->p1.x + 1)
  367. return -EINVAL;
  368. /* check if allocation would fit in scan area */
  369. if (num_slots > tcm->width * LEN(field->p0.y, field->p1.y))
  370. return -ENOSPC;
  371. x = field->p0.x;
  372. y = field->p0.y;
  373. /* find num_slots consecutive free slots to the left */
  374. while (found < num_slots) {
  375. if (y < 0)
  376. return -ENOSPC;
  377. /* remember bottom-right corner */
  378. if (found == 0) {
  379. area->p1.x = x;
  380. area->p1.y = y;
  381. }
  382. /* skip busy regions */
  383. p = pvt->map[x][y];
  384. if (p) {
  385. /* move to left of 2D areas, top left of 1D */
  386. x = p->p0.x;
  387. if (!p->is2d)
  388. y = p->p0.y;
  389. /* start over */
  390. found = 0;
  391. } else {
  392. /* count consecutive free slots */
  393. found++;
  394. if (found == num_slots)
  395. break;
  396. }
  397. /* move to the left */
  398. if (x == 0)
  399. y--;
  400. x = (x ? : tcm->width) - 1;
  401. }
  402. /* set top-left corner */
  403. area->p0.x = x;
  404. area->p0.y = y;
  405. return 0;
  406. }
  407. /**
  408. * Find a place for a 2D area of given size inside a scan field based on its
  409. * alignment needs.
  410. *
  411. * @param w width of desired area
  412. * @param h height of desired area
  413. * @param align desired area alignment
  414. * @param area pointer to the area that will be set to the best position
  415. *
  416. * @return 0 on success, non-0 error value on failure.
  417. */
  418. static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
  419. struct tcm_area *area)
  420. {
  421. s32 ret = 0;
  422. struct tcm_area field = {0};
  423. u16 boundary_x, boundary_y;
  424. struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
  425. if (align > 1) {
  426. /* prefer top-left corner */
  427. boundary_x = pvt->div_pt.x - 1;
  428. boundary_y = pvt->div_pt.y - 1;
  429. /* expand width and height if needed */
  430. if (w > pvt->div_pt.x)
  431. boundary_x = tcm->width - 1;
  432. if (h > pvt->div_pt.y)
  433. boundary_y = tcm->height - 1;
  434. assign(&field, 0, 0, boundary_x, boundary_y);
  435. ret = scan_l2r_t2b(tcm, w, h, align, &field, area);
  436. /* scan whole container if failed, but do not scan 2x */
  437. if (ret != 0 && (boundary_x != tcm->width - 1 ||
  438. boundary_y != tcm->height - 1)) {
  439. /* scan the entire container if nothing found */
  440. assign(&field, 0, 0, tcm->width - 1, tcm->height - 1);
  441. ret = scan_l2r_t2b(tcm, w, h, align, &field, area);
  442. }
  443. } else if (align == 1) {
  444. /* prefer top-right corner */
  445. boundary_x = pvt->div_pt.x;
  446. boundary_y = pvt->div_pt.y - 1;
  447. /* expand width and height if needed */
  448. if (w > (tcm->width - pvt->div_pt.x))
  449. boundary_x = 0;
  450. if (h > pvt->div_pt.y)
  451. boundary_y = tcm->height - 1;
  452. assign(&field, tcm->width - 1, 0, boundary_x, boundary_y);
  453. ret = scan_r2l_t2b(tcm, w, h, align, &field, area);
  454. /* scan whole container if failed, but do not scan 2x */
  455. if (ret != 0 && (boundary_x != 0 ||
  456. boundary_y != tcm->height - 1)) {
  457. /* scan the entire container if nothing found */
  458. assign(&field, tcm->width - 1, 0, 0, tcm->height - 1);
  459. ret = scan_r2l_t2b(tcm, w, h, align, &field,
  460. area);
  461. }
  462. }
  463. return ret;
  464. }
  465. /* check if an entire area is free */
  466. static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h)
  467. {
  468. u16 x = 0, y = 0;
  469. for (y = y0; y < y0 + h; y++) {
  470. for (x = x0; x < x0 + w; x++) {
  471. if (map[x][y])
  472. return false;
  473. }
  474. }
  475. return true;
  476. }
  477. /* fills an area with a parent tcm_area */
  478. static void fill_area(struct tcm *tcm, struct tcm_area *area,
  479. struct tcm_area *parent)
  480. {
  481. s32 x, y;
  482. struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
  483. struct tcm_area a, a_;
  484. /* set area's tcm; otherwise, enumerator considers it invalid */
  485. area->tcm = tcm;
  486. tcm_for_each_slice(a, *area, a_) {
  487. for (x = a.p0.x; x <= a.p1.x; ++x)
  488. for (y = a.p0.y; y <= a.p1.y; ++y)
  489. pvt->map[x][y] = parent;
  490. }
  491. }
  492. /**
  493. * Compares a candidate area to the current best area, and if it is a better
  494. * fit, it updates the best to this one.
  495. *
  496. * @param x0, y0, w, h top, left, width, height of candidate area
  497. * @param field scan field
  498. * @param criteria scan criteria
  499. * @param best best candidate and its scores
  500. *
  501. * @return 1 (true) if the candidate area is known to be the final best, so no
  502. * more searching should be performed
  503. */
  504. static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
  505. struct tcm_area *field, s32 criteria,
  506. struct score *best)
  507. {
  508. struct score me; /* score for area */
  509. /*
  510. * NOTE: For horizontal bias we always give the first found, because our
  511. * scan is horizontal-raster-based and the first candidate will always
  512. * have the horizontal bias.
  513. */
  514. bool first = criteria & CR_BIAS_HORIZONTAL;
  515. assign(&me.a, x0, y0, x0 + w - 1, y0 + h - 1);
  516. /* calculate score for current candidate */
  517. if (!first) {
  518. get_neighbor_stats(tcm, &me.a, &me.n);
  519. me.neighs = me.n.edge + me.n.busy;
  520. get_nearness_factor(field, &me.a, &me.f);
  521. }
  522. /* the 1st candidate is always the best */
  523. if (!best->a.tcm)
  524. goto better;
  525. BUG_ON(first);
  526. /* diagonal balance check */
  527. if ((criteria & CR_DIAGONAL_BALANCE) &&
  528. best->neighs <= me.neighs &&
  529. (best->neighs < me.neighs ||
  530. /* this implies that neighs and occupied match */
  531. best->n.busy < me.n.busy ||
  532. (best->n.busy == me.n.busy &&
  533. /* check the nearness factor */
  534. best->f.x + best->f.y > me.f.x + me.f.y)))
  535. goto better;
  536. /* not better, keep going */
  537. return 0;
  538. better:
  539. /* save current area as best */
  540. memcpy(best, &me, sizeof(me));
  541. best->a.tcm = tcm;
  542. return first;
  543. }
  544. /**
  545. * Calculate the nearness factor of an area in a search field. The nearness
  546. * factor is smaller if the area is closer to the search origin.
  547. */
  548. static void get_nearness_factor(struct tcm_area *field, struct tcm_area *area,
  549. struct nearness_factor *nf)
  550. {
  551. /**
  552. * Using signed math as field coordinates may be reversed if
  553. * search direction is right-to-left or bottom-to-top.
  554. */
  555. nf->x = (s32)(area->p0.x - field->p0.x) * 1000 /
  556. (field->p1.x - field->p0.x);
  557. nf->y = (s32)(area->p0.y - field->p0.y) * 1000 /
  558. (field->p1.y - field->p0.y);
  559. }
  560. /* get neighbor statistics */
  561. static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
  562. struct neighbor_stats *stat)
  563. {
  564. s16 x = 0, y = 0;
  565. struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
  566. /* Clearing any exisiting values */
  567. memset(stat, 0, sizeof(*stat));
  568. /* process top & bottom edges */
  569. for (x = area->p0.x; x <= area->p1.x; x++) {
  570. if (area->p0.y == 0)
  571. stat->edge++;
  572. else if (pvt->map[x][area->p0.y - 1])
  573. stat->busy++;
  574. if (area->p1.y == tcm->height - 1)
  575. stat->edge++;
  576. else if (pvt->map[x][area->p1.y + 1])
  577. stat->busy++;
  578. }
  579. /* process left & right edges */
  580. for (y = area->p0.y; y <= area->p1.y; ++y) {
  581. if (area->p0.x == 0)
  582. stat->edge++;
  583. else if (pvt->map[area->p0.x - 1][y])
  584. stat->busy++;
  585. if (area->p1.x == tcm->width - 1)
  586. stat->edge++;
  587. else if (pvt->map[area->p1.x + 1][y])
  588. stat->busy++;
  589. }
  590. }