From 0dfbe85142334806a19a4f8122b2519df7fd0195 Mon Sep 17 00:00:00 2001 From: R Ramachandra Date: Fri, 9 Apr 2010 17:16:51 -0500 Subject: Moved to New Tiler APIs defined in tcm.h, add multi-continer support Signed-off-by: R Ramachandra --- drivers/media/video/tiler/tcm/tcm.c | 1317 +++++++++++++++++------------ drivers/media/video/tiler/tcm/tcm.h | 342 ++++++-- drivers/media/video/tiler/tcm/tcm_rr.h | 135 +++ drivers/media/video/tiler/tcm/tcm_sita.h | 15 + drivers/media/video/tiler/tcm/tcm_utils.c | 130 +-- drivers/media/video/tiler/tcm/tcm_utils.h | 18 +- 6 files changed, 1224 insertions(+), 733 deletions(-) create mode 100644 drivers/media/video/tiler/tcm/tcm_rr.h create mode 100644 drivers/media/video/tiler/tcm/tcm_sita.h (limited to 'drivers/media/video/tiler/tcm') diff --git a/drivers/media/video/tiler/tcm/tcm.c b/drivers/media/video/tiler/tcm/tcm.c index 9f4f7ced9588..4f0c7649e9b7 100644 --- a/drivers/media/video/tiler/tcm/tcm.c +++ b/drivers/media/video/tiler/tcm/tcm.c @@ -1,178 +1,259 @@ /* -* tcm.c -* -* Author: Ravi Ramachandra -* -* Tiler 2D and 1D Container Management Algorithm. -* -* Copyright (C) 2009-2010 Texas Instruments, Inc. -* -* This package is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -* -* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR -* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED -* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. -* -*/ + * tcm.c + * + * Author: Ravi Ramachandra + * + * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation) algorithm + * + * Copyright (C) 2009-2010 Texas Instruments, Inc. + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ -#include -#include -#include "tcm_pri.h" -#include "tcm.h" +#include "tcm_rr.h" +#include "tcm_sita.h" #include "tcm_utils.h" -/********************************************* - * POSITIONING & OPTIMIZATION TWEAKS -*********************************************/ - -/* Restricts scanning unecessary tiles */ -/*By enabling this X_SCAN LIMITER, we scan consective line only till the -previous found x0, thus eliminating candidates for selection during scan only */ -#define X_SCAN_LIMITER -/*By enabling this Y_SCAN_LIMITER we limit scan going down(or up) if we found -that the candidate's y0 is same as scan area's start scan */ -#define Y_SCAN_LIMITER +/* Individual selection criteria for different scan areas */ +static s32 g_scan_criteria_l2r_t2b = CR_BIAS_HORIZONTAL; +static s32 g_scan_criteria_r2l_t2b = CR_DIAGONAL_BALANCE; +#ifdef SCAN_BOTTOM_UP +static s32 g_scan_criteria_r2l_b2t = CR_FIRST_FOUND; +static s32 g_scan_criteria_l2r_b2t = CR_DIAGONAL_BALANCE; +#endif -/* Enabling this will HARD restrict 1D to as specified in g_div_ln...'s y1 */ -/* #define RESTRICT_1D */ +/********************************************* + * TCM API - Sita Implementation + *********************************************/ +static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align, + struct tcm_area *allocated_area); +static s32 sita_reserve_1d(struct tcm *tcm, u32 slots, struct tcm_area + *allocated_pages); +static s32 sita_free(struct tcm *tcm, struct tcm_area *to_be_removed_area); +static s32 sita_get_parent(struct tcm *tcm, struct tcm_pt *pt, + struct tcm_area *area); +static s32 sita_deinit(struct tcm *tcm); /*********************************************/ -/* ******************************************** - * GLOBALS +/********************************************* + * Main Scanner functions *********************************************/ -/* global Container that keeps a map of which tile is occupied -and which tiler is not occupied */ -static struct tiler_page g_area_container[MAX_X_DIMMENSION][MAX_Y_DIMMENSION]; +static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 stride, + struct tcm_area *allocated_area); -/* This list keeps a track of all the allocations that happened in terms -of area allocated, this list is checked for removing any allocations */ -struct area_spec_list *g_allocation_list; +static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, + u16 stride, struct tcm_area *scan_area, + struct tcm_area *alloc_area); -/*Vertical line divider between 64 and 32 aligned scan areas */ -struct area_spec g_div_ln_btw_64_and_32_align = {192, 0, 192, 96}; +static s32 scan_r2l_t2b(struct tcm *tcm, u16 w, u16 h, u16 stride, + struct tcm_area *scan_area, + struct tcm_area *alloc_area); -/* Just some temp ID, which will roll over 32K */ -u32 g_id; +#ifdef SCAN_BOTTOM_UP +static s32 scan_l2r_b2t(struct tcm *tcm, u16 w, u16 h, u16 stride, + struct tcm_area *scan_area, + struct tcm_area *alloc_area); -static struct mutex g_mutex; +static s32 scan_r2l_b2t(struct tcm *tcm, u16 w, u16 h, u16 stride, + struct tcm_area *scan_area, + struct tcm_area *alloc_area); +#endif +static s32 scan_r2l_b2t_one_dim(struct tcm *tcm, u32 num_of_pages, + struct tcm_area *scan_area, + struct tcm_area *alloc_area); -/* Individual selection criteria for different scan areas */ -static s32 g_scan_criteria_l2r_t2b = CR_BIAS_HORIZONTAL; -static s32 g_scan_criteria_l2r_b2t = CR_DIAGONAL_BALANCE; -static s32 g_scan_criteria_r2l_t2b = CR_DIAGONAL_BALANCE; -static s32 g_scan_criteria_r2l_b2t = CR_FIRST_FOUND; +/********************************************* + * Support Infrastructure Methods + *********************************************/ +static s32 check_fit_r_and_b(struct tcm *tcm, u16 w, u16 h, u16 left_x, + u16 top_y); -/*********************************************/ +static s32 check_fit_r_one_dim(struct tcm *tcm, u16 x, u16 y, u32 num_of_pages, + u16 *busy_x, u16 *busy_y); +static s32 select_candidate(struct tcm *tcm, IN u16 w, IN u16 h, + IN u16 num_short_listed, + IN struct area_spec_list *short_listed, + IN struct tcm_area *scan_area, IN s32 criteria, + OUT struct tcm_area *alloc_area); -/********************************************* - * LOCAL METHODS - *********************************************/ -static s32 scan_areas_and_find_fit(u16 w, u16 h, u16 stride, - struct area_spec *allocated_area); -static s32 scan_l2r_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, - struct area_spec *alloc_area); -static s32 scan_r2l_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, - struct area_spec *alloc_area); -static s32 scan_l2r_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, - struct area_spec *alloc_area); -static s32 scan_r2l_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, - struct area_spec *alloc_area); -static s32 scan_r2l_b2t_one_dim(u32 num_of_pages, struct area_spec *scan_area, - struct area_spec *alloc_area); - -/* Support Infrastructure functions */ -static s32 check_fit_r_and_b(u16 w, u16 h, u16 left_x, u16 top_y); -static s32 check_fit_r_one_dim(u16 x, u16 y, u32 num_of_pages, u16 *busy_x, - u16 *busy_y); -static s32 select_candidate(IN u16 w, IN u16 h, IN u16 num_short_listed, - IN struct area_spec_list *short_listed, IN struct area_spec *scan_area, - IN s32 criteria, OUT struct area_spec *alloc_area); -/* old selecte candidate will be deprecated after testing new one */ -static s32 get_nearness_factor(struct area_spec *scan_area, - struct area_spec *candidate, struct nearness_factor *nf); -static s32 get_busy_neigh_stats(u16 width, u16 height, - struct area_spec *top_left_corner, - struct neighbour_stats *neighbour_stat); -static s32 insert_area_with_tiler_page(struct area_spec *area, - struct tiler_page tile); -static s32 insert_pages_with_tiler_page(struct area_spec *area, - struct tiler_page tile); +static s32 get_nearness_factor(struct tcm_area *scan_area, + struct tcm_area *candidate, struct nearness_factor *nf); + +static s32 get_busy_neigh_stats(struct tcm *tcm, u16 width, u16 height, + struct tcm_area *top_left_corner, + struct neighbour_stats *neighbour_stat); +static s32 insert_pages_with_tiler_page(struct tcm *tcm, + struct tcm_area *area, struct tiler_page tile); + +static s32 insert_area_with_tiler_page(struct tcm *tcm, + struct tcm_area *area, struct tiler_page tile); + +static s32 move_left(struct tcm *tcm, u16 x, u16 y, u32 num_of_pages, + u16 *xx, u16 *yy); +static s32 move_right(struct tcm *tcm, u16 x, u16 y, u32 num_of_pages, + u16 *xx, u16 *yy); /*********************************************/ -/** - * @description: Initializes tiler container. - * - * @input: None - * - * @return 0 on success, non-0 error value on failure. - */ -s32 init_tiler(void) +struct tcm *sita_init(u16 width, u16 height, void *attr) { + struct tcm *tmp = NULL; + struct sita_pvt *pvt = NULL; struct tiler_page init_tile; - struct area_spec area = {0}; + struct tcm_area area; + struct tcm_pt *tmp_pt = (struct tcm_pt *)attr; + s32 i = 0; + memset(&area, 0, sizeof(struct tcm_area)); + + if (!(width & height)) { + PE("width/height is Zero\n"); + return tmp; + } + + tmp = kmalloc(sizeof(struct tcm), GFP_KERNEL); + if (tmp == NULL) + return tmp; + /* TO DO: Do i need to restrict width and height??? */ init_tile.is_occupied = 0; - init_tile.parent_area.x0 = 0; - init_tile.parent_area.x1 = 0; - init_tile.parent_area.y0 = 0; - init_tile.parent_area.y1 = 0; + init_tile.parent_area.p0.x = 0; + init_tile.parent_area.p1.y = 0; + init_tile.parent_area.p1.x = 0; + init_tile.parent_area.p1.y = 0; init_tile.reserved = 0; init_tile.type = 0; - area.x1 = MAX_X_DIMMENSION - 1; - area.y1 = MAX_Y_DIMMENSION - 1; + pvt = kmalloc(sizeof(struct sita_pvt), GFP_KERNEL); + if (pvt == NULL) { + kfree(tmp); + tmp = NULL; + return tmp; + } - mutex_init(&g_mutex); - MUTEX_LOCK(&g_mutex); - insert_area_with_tiler_page(&area, init_tile); - MUTEX_REL(&g_mutex); - return TilerErrorNone; + pvt->height = height; + pvt->width = width; + mutex_init(&(pvt->mtx)); + pvt->tcm_map = NULL; + + + /* Creating tam map */ + pvt->tcm_map = (struct tiler_page **) + kmalloc(sizeof(struct tiler_page *) * pvt->height, GFP_KERNEL); + + if (pvt->tcm_map == NULL) { + kfree(pvt); + pvt = NULL; + kfree(tmp); + tmp = NULL; + return tmp; + } + + for (i = 0; i < pvt->height; ++i) { + pvt->tcm_map[i] = NULL; + pvt->tcm_map[i] = (struct tiler_page *) + kmalloc(sizeof(struct tiler_page) * pvt->width, GFP_KERNEL); + if (pvt->tcm_map[i] == NULL) { + for (i -= 1; i >= 0; i--) { + kfree(pvt->tcm_map[i]); + pvt->tcm_map[i] = NULL; + } + kfree(pvt->tcm_map); + pvt->tcm_map = NULL; + kfree(pvt); + pvt = NULL; + kfree(tmp); + tmp = NULL; + return tmp; + } + } + + if (tmp_pt && tmp_pt->x < pvt->width && tmp_pt->y < pvt->height) { + pvt->div_pt.x = tmp_pt->x; + pvt->div_pt.y = tmp_pt->y; + + } else { + /* Defaulting to 3:1 ratio on width for 2D area split */ + /* Defaulting to 3:1 ratio on height for 2D and 1D split */ + pvt->div_pt.x = (pvt->width*3)/4; + pvt->div_pt.y = (pvt->height*3)/4; + } + + memset(&area, 0, sizeof(struct tcm_area)); + area.p1.x = width-1; + area.p1.y = height-1; + + MUTEX_LOCK(&(pvt->mtx)); + insert_area_with_tiler_page(tmp, &area, init_tile); + MUTEX_REL(&(pvt->mtx)); + + tmp->pvt = (void *)pvt; + + /*Updating the pointers to SiTA implementation APIs*/ + tmp->reserve_2d = sita_reserve_2d; + tmp->reserve_1d = sita_reserve_1d; + tmp->get_parent = sita_get_parent; + tmp->free = sita_free; + tmp->deinit = sita_deinit; + return tmp; } -/** - * @description: DeInitializes tiler container. - * removes existing allocations - * - * @input: None - * - * @return 0 on success, non-0 error value on failure. - */ -s32 deinit_tiler(void) +static s32 sita_deinit(struct tcm *tcm) { struct tiler_page init_tile; - struct area_spec area = {0}; - /* Cleaning all the entries in the list and marking tiler container - as free */ + struct sita_pvt *pvt = NULL; + struct tcm_area area; + s32 i = 0; init_tile.is_occupied = 0; - init_tile.parent_area.x0 = 0; - init_tile.parent_area.x1 = 0; - init_tile.parent_area.y0 = 0; - init_tile.parent_area.y1 = 0; + init_tile.parent_area.p0.x = 0; + init_tile.parent_area.p1.y = 0; + init_tile.parent_area.p1.x = 0; + init_tile.parent_area.p1.y = 0; init_tile.reserved = 0; init_tile.type = 0; - area.x1 = MAX_X_DIMMENSION - 1; - area.y1 = MAX_Y_DIMMENSION - 1; + pvt = (struct sita_pvt *)tcm->pvt; + if (pvt == NULL) { + PE("Private struct NULL\n"); + return TilerErrorGeneral; + } + + memset(&area, 0, sizeof(struct tcm_area)); + area.p1.x = pvt->width-1; + area.p1.y = pvt->height-1; + + MUTEX_LOCK(&(pvt->mtx)); + insert_area_with_tiler_page(tcm, &area, init_tile); + MUTEX_REL(&(pvt->mtx)); + + mutex_destroy(&(pvt->mtx)); + + for (i = 0; i < pvt->height; i++) { + kfree(pvt->tcm_map[i]); + pvt->tcm_map[i] = NULL; + } + kfree(pvt->tcm_map); + pvt->tcm_map = NULL; - MUTEX_LOCK(&g_mutex); - insert_area_with_tiler_page(&area, init_tile); - clean_list(&g_allocation_list); - MUTEX_REL(&g_mutex); - mutex_destroy(&g_mutex); return TilerErrorNone; } + + /** * @description: Allocate 1d pages if the required number of pages are * available in the container @@ -182,11 +263,14 @@ s32 deinit_tiler(void) * @return 0 on success, non-0 error value on failure. On success * allocated_pages contain co-ordinates of start and end Tiles(inclusive) */ -s32 allocate_1d_pages(u32 num_of_pages, struct area_spec *allocated_pages) +static s32 sita_reserve_1d(struct tcm *tcm, u32 num_of_pages, + struct tcm_area *allocated_pages) { + s32 ret = TilerErrorNone; - struct area_spec scan_area = {0, 0, 0, 0}; + struct tcm_area scan_area = {0, NULL, {0, 0}, {0, 0} }; struct tiler_page tile; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; memset(&tile, 0, sizeof(struct tiler_page)); P1("Allocate %d pages\n", num_of_pages); @@ -197,22 +281,22 @@ s32 allocate_1d_pages(u32 num_of_pages, struct area_spec *allocated_pages) return TilerErrorInvalidArg; } /* Delibrately checking outside to give out relavent error info */ - if (num_of_pages > (MAX_X_DIMMENSION * MAX_Y_DIMMENSION)) { + if (num_of_pages > (pvt->width * pvt->height)) { PE("num_of_pages exceed maximum pages available(%d)\n", - (MAX_X_DIMMENSION * MAX_Y_DIMMENSION)); + (pvt->width * pvt->height)); return TilerErrorNoRoom; } - MUTEX_LOCK(&g_mutex); + MUTEX_LOCK(&(pvt->mtx)); #ifdef RESTRICT_1D /*scan within predefine 1D boundary */ - assign(&scan_area, (MAX_X_DIMMENSION-1), (MAX_Y_DIMMENSION - 1), 0, - g_div_ln_btw_64_and_32_align.y1); + assign(&scan_area, (pvt->width - 1), (pvt->height - 1), 0, + tcm->div_spec.p1.y); #else /* Scanning entire container */ - assign(&scan_area, MAX_X_DIMMENSION - 1, MAX_Y_DIMMENSION - 1, 0, 0); + assign(&scan_area, pvt->width - 1, pvt->height - 1, 0, 0); #endif - ret = scan_r2l_b2t_one_dim(num_of_pages, &scan_area, allocated_pages); - + ret = scan_r2l_b2t_one_dim(tcm, num_of_pages, + &scan_area, allocated_pages); /* There is not much to select, we pretty much give the first one which accomodates */ if (ret != TilerErrorNone) { @@ -220,19 +304,19 @@ s32 allocate_1d_pages(u32 num_of_pages, struct area_spec *allocated_pages) } else { P("Yahoo found a fit: %s\n", AREA_STR(a_str, allocated_pages)); tile.is_occupied = OCCUPIED; - assign(&tile.parent_area, allocated_pages->x0, - allocated_pages->y0, allocated_pages->x1, - allocated_pages->y1); + assign(&tile.parent_area, allocated_pages->p0.x, + allocated_pages->p0.y, allocated_pages->p1.x, + allocated_pages->p1.y); /* some id, not useful now */ - tile.reserved = g_id++; + tile.reserved = pvt->id++; /* Saying that type is 1d */ - tile.type = ONE_D; + tile.type = TCM_1D; /* inserting into tiler container */ - insert_pages_with_tiler_page(allocated_pages, tile); + insert_pages_with_tiler_page(tcm, allocated_pages, tile); /*updating the list of allocations */ - insert_element(&g_allocation_list, allocated_pages, ONE_D); + insert_element(&pvt->res_list, allocated_pages, TCM_1D); } - MUTEX_REL(&g_mutex); + MUTEX_REL(&(pvt->mtx)); return ret; } @@ -246,18 +330,19 @@ s32 allocate_1d_pages(u32 num_of_pages, struct area_spec *allocated_pages) * allocated_area contain co-ordinates of TL corner Tile and BR corner Tile of * the rectangle (inclusive) */ -s32 allocate_2d_area(u16 w, u16 h, enum alignment align, - struct area_spec *allocated_area) +static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align, + struct tcm_area *allocated_area) { s32 ret = TilerErrorNone; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; u16 stride = ALIGN_STRIDE(align); struct tiler_page tile; - + memset(&tile, 0, sizeof(struct tiler_page)); P1("\n\nStart of allocation 2D Area for WxH : (%d x %d) with Alignment\ %d \n", w, h, stride); /* Checking for input arguments */ - if (allocated_area == NULL) { + if (allocated_area == NULL || tcm == NULL) { PE("NULL input found\n"); return TilerErrorInvalidArg; } @@ -267,42 +352,42 @@ s32 allocate_2d_area(u16 w, u16 h, enum alignment align, return TilerErrorNotSupported; } /*check if width and height are within limits */ - if (w > MAX_X_DIMMENSION || w == 0 || h > MAX_Y_DIMMENSION || h == 0) { + if (w > pvt->width || w == 0 || h > pvt->height || h == 0) { PE("Invalid dimension:: %d x %d\n", w, h); return TilerErrorInvalidDimension; } - MUTEX_LOCK(&g_mutex); - ret = scan_areas_and_find_fit(w, h, stride, allocated_area); + MUTEX_LOCK(&(pvt->mtx)); + ret = scan_areas_and_find_fit(tcm, w, h, stride, allocated_area); if (ret != TilerErrorNone) { PE("Did not find anything in the given area\n"); } else { P("Yahoo found a fit: %s\n", AREA_STR(a_str, allocated_area)); tile.is_occupied = OCCUPIED; - assign(&tile.parent_area, allocated_area->x0, - allocated_area->y0, allocated_area->x1, - allocated_area->y1); + assign(&tile.parent_area, allocated_area->p0.x, + allocated_area->p0.y, allocated_area->p1.x, + allocated_area->p1.y); /* some id, not useful now */ - tile.reserved = g_id++; + tile.reserved = pvt->id++; /* Saying that type is 2D */ - tile.type = TWO_D; + tile.type = TCM_2D; /* inserting into tiler container */ - ret = insert_area_with_tiler_page(allocated_area, tile); + ret = insert_area_with_tiler_page(tcm, allocated_area, tile); if (ret == TilerErrorNone) { /*updating the list of allocations */ - insert_element(&g_allocation_list, - allocated_area, TWO_D); + insert_element(&(pvt->res_list), + allocated_area, TCM_2D); } else { PE("Could not insert area\n %s\n", AREA_STR(a_str, - allocated_area)); + allocated_area)); } } - MUTEX_REL(&g_mutex); + MUTEX_REL(&(pvt->mtx)); return ret; } /** - * @description: Deallocate 2d or 1D allocations if previously allocated + * @description: unreserve 2d or 1D allocations if previously allocated * * @input:'to_be_removed_area' specification: for 2D this should contain * TL Corner and BR Corner of the 2D area, or for 1D allocation this should @@ -313,45 +398,45 @@ s32 allocate_2d_area(u16 w, u16 h, enum alignment align, * corresponding tiles are marked 'NOT_OCCUPIED' * */ -s32 deallocate(struct area_spec *to_be_removed_area) + +static s32 sita_free(struct tcm *tcm, struct tcm_area *to_be_removed_area) { s32 ret = TilerErrorNone; - struct tiler_page reset_tile = { NOT_OCCUPIED, {0, 0, 0, 0}, 0, 0}; + struct tiler_page reset_tile; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; u16 area_type; - - MUTEX_LOCK(&g_mutex); + memset(&reset_tile, 0, sizeof(struct tiler_page)); + reset_tile.is_occupied = NOT_OCCUPIED; + MUTEX_LOCK(&(pvt->mtx)); /*First we check if the given Area is aleast valid in our list*/ - ret = rem_element_with_match(&g_allocation_list, to_be_removed_area, - &area_type); + ret = rem_element_with_match(&(pvt->res_list), to_be_removed_area, + &area_type); /* If we found a positive match & removed the area details from list * then we clear the contents of the associated tiles in the global * container*/ if (ret == TilerErrorNone) { - if (area_type == TWO_D) { - P1("De-allocating TWO_D allocation %s\n", - AREA_STR(a_str, to_be_removed_area)); + if (area_type == TCM_2D) { + P1("De-allocating TCM_2D allocation %s\n", + AREA_STR(a_str, to_be_removed_area)); /*Reset tiles are inserted, ignoring ret values delibrately */ - ret = insert_area_with_tiler_page( - to_be_removed_area, reset_tile); + ret = insert_area_with_tiler_page(tcm, + to_be_removed_area, reset_tile); } else { - P1("De-allocating ONE_D allocation %s\n", - AREA_STR(a_str, to_be_removed_area)); - ret = insert_pages_with_tiler_page(to_be_removed_area, - reset_tile); + P1("De-allocating TCM_1D allocation %s\n", + AREA_STR(a_str, to_be_removed_area)); + ret = insert_pages_with_tiler_page(tcm, + to_be_removed_area, reset_tile); } } else { PE("Did not find a Match to remove\n"); } - - MUTEX_REL(&g_mutex); + MUTEX_REL(&(pvt->mtx)); return ret; - } - /** * @description: raster scan right to left from top to bottom; find if there is * a free area to fit a given w x h inside the 'scan area'. If there is a free @@ -366,39 +451,41 @@ s32 deallocate(struct area_spec *to_be_removed_area) * the 'alloc_area' area contains TL and BR corners of the allocated area * */ -s32 scan_r2l_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, - struct area_spec *alloc_area) +s32 scan_r2l_t2b(struct tcm *tcm, u16 w, u16 h, u16 stride, + struct tcm_area *scan_area, struct tcm_area *alloc_area) { + s32 ret = TilerErrorNone; s32 xx = 0, yy = 0; s16 start_x = -1, end_x = -1, start_y = -1, end_y = -1; s16 found_x = -1, found_y = -1; u16 remainder; struct area_spec_list *short_listed = NULL; - struct area_spec candidate_area = {0, 0, 0, 0}; + struct tcm_area candidate_area; u16 num_short_listed = 0; - s32 ret = TilerErrorNone; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; + memset(&candidate_area, 0, sizeof(struct tcm_area)); P2("Scanning From Right 2 Left Top 2 Bottom: ScanArea: %s\n", - AREA_STR(a_str, scan_area)); + AREA_STR(a_str, scan_area)); /*Basic checks */ - if (scan_area == NULL || alloc_area == NULL) { + if (scan_area == NULL || alloc_area == NULL || tcm == NULL) { PE("Null value found\n"); return TilerErrorInvalidArg; } /*Check if the scan area co-ordinates are valid */ - if ((scan_area->x0 < scan_area->x1) || - (scan_area->y1 < scan_area->y0)) { + if ((scan_area->p0.x < scan_area->p1.x) || + (scan_area->p1.y < scan_area->p0.y)) { PE("Invalid scan area: %s\n", AREA_STR(a_str, scan_area)); return TilerErrorInvalidScanArea; } - start_x = scan_area->x0; - end_x = scan_area->x1; - start_y = scan_area->y0; - end_y = scan_area->y1; + start_x = scan_area->p0.x; + end_x = scan_area->p1.x; + start_y = scan_area->p0.y; + end_y = scan_area->p1.y; /* Check if we have a scan area bigger than the given input width and height */ @@ -432,7 +519,7 @@ s32 scan_r2l_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, P2("Final stride : %d\n, start_x : %d end_x : %d start_y :\ %d end_y : %d\n", stride, start_x, end_x, start_y, - end_y); + end_y); /* Start scanning: These scans are always inclusive ones so if we are given a start x = 0 is a valid value so if we have a end_x = 255, @@ -440,9 +527,10 @@ s32 scan_r2l_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, */ for (yy = start_y; yy <= end_y; ++yy) { for (xx = start_x; xx >= end_x; xx -= stride) { - if (g_area_container[xx][yy].is_occupied == - NOT_OCCUPIED) { - if (FIT == check_fit_r_and_b(w, h, xx, yy)) { + if (pvt->tcm_map[xx][yy].is_occupied == + NOT_OCCUPIED) { + if (FIT == check_fit_r_and_b(tcm, w, h, + xx, yy)) { P3("Found Free Shoulder at:\ (%d, %d)\n", xx, yy); found_x = xx; @@ -451,7 +539,7 @@ s32 scan_r2l_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, co-ordinate, reusing Area */ assign(&candidate_area, xx, yy, 0, 0); insert_element(&short_listed, - &candidate_area, TWO_D); + &candidate_area, TCM_2D); num_short_listed++; /*changing upper bound on x direction */ #ifdef X_SCAN_LIMITER @@ -463,10 +551,10 @@ s32 scan_r2l_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, /* Optimization required only for Non Aligned, Aligned anyways skip by 32/64 tiles at a time */ if (stride == 1 && - g_area_container[xx][yy].type == - TWO_D) { - xx = g_area_container - [xx][yy].parent_area.x0; + pvt->tcm_map[xx][yy].type == + TCM_2D) { + xx = pvt->tcm_map + [xx][yy].parent_area.p0.x; P3("Moving to parent location start_x\ (%d %d)\n", xx, yy); } @@ -491,8 +579,8 @@ s32 scan_r2l_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, } /*Now if we are here it implies we have potential candidates*/ - ret = select_candidate(w, h, num_short_listed, short_listed, scan_area, - g_scan_criteria_r2l_t2b, alloc_area); + ret = select_candidate(tcm, w, h, num_short_listed, short_listed, + scan_area, g_scan_criteria_r2l_t2b, alloc_area); if (ret != TilerErrorNone) PE("Error in Selecting a Candidate\n"); @@ -505,6 +593,7 @@ s32 scan_r2l_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, } +#ifdef SCAN_BOTTOM_UP /** * @description: raster scan right to left from bottom to top; find if there is * a free area to fit a given w x h inside the 'scan area'. If there is a free @@ -519,9 +608,10 @@ s32 scan_r2l_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, * the 'alloc_area' area contains TL and BR corners of the allocated area * */ -s32 scan_r2l_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, - struct area_spec *alloc_area) +static s32 scan_r2l_b2t(struct tcm *tcm, u16 w, u16 h, u16 stride, + struct tcm_area *scan_area, struct tcm_area *alloc_area) { + s32 ret = TilerErrorNone; /* TO DO: Should i check scan area? Might have to take it as input during initialization @@ -531,27 +621,27 @@ s32 scan_r2l_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, s16 found_x = -1, found_y = -1; u16 remainder; struct area_spec_list *short_listed = NULL; - struct area_spec candidate_area = {0, 0, 0, 0}; + struct tcm_area candidate_area; u16 num_short_listed = 0; - s32 ret = TilerErrorNone; - + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; + memset(&candidate_area, 0, sizeof(struct tcm_area)); P2("Scanning From Right 2 Left Bottom 2 Top, ScanArea: %s\n", - AREA_STR(a_str, scan_area)); - start_x = scan_area->x0; - end_x = scan_area->x1; - start_y = scan_area->y0; - end_y = scan_area->y1; + AREA_STR(a_str, scan_area)); + start_x = scan_area->p0.x; + end_x = scan_area->p1.x; + start_y = scan_area->p0.y; + end_y = scan_area->p1.y; /*Basic checks */ - if (scan_area == NULL || alloc_area == NULL) { + if (scan_area == NULL || alloc_area == NULL || tcm == NULL) { PE("Null value found\n"); return TilerErrorInvalidArg; } /*Check if the scan area co-ordinates are valid */ - if ((scan_area->x1 < scan_area->x0) || - (scan_area->y1 < scan_area->y0)) { + if ((scan_area->p1.x < scan_area->p0.x) || + (scan_area->p1.y < scan_area->p0.y)) { PE("Invalid scan area: %s\n", AREA_STR(a_str, scan_area)); return TilerErrorInvalidScanArea; } @@ -595,17 +685,18 @@ s32 scan_r2l_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, */ for (yy = start_y; yy >= end_y; --yy) { for (xx = start_x; xx >= end_x; xx -= stride) { - if (!g_area_container[xx][yy].is_occupied) { - if (check_fit_r_and_b(w, h, xx, yy) == FIT) { + if (!pvt->tcm_map[xx][yy].is_occupied) { + if (check_fit_r_and_b(tcm, w, h, xx, yy) + == FIT) { P3("Found Free Shoulder at: (%d, %d)\n", - xx, yy); + xx, yy); found_x = xx; found_y = yy; /* Insert this candidate, it is just a co-ordinate, reusing Area */ assign(&candidate_area, xx, yy, 0, 0); insert_element(&short_listed, - &candidate_area, TWO_D); + &candidate_area, TCM_2D); num_short_listed++; /*changing upper bound on x direction */ #ifdef X_SCAN_LIMITER @@ -616,10 +707,10 @@ s32 scan_r2l_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, } else { /* Optimization required only for Non Aligned, Aligned anyways skip by 32/64 tiles at a time */ - if (stride == 1 && g_area_container - [xx][yy].type == TWO_D) { - xx = g_area_container - [xx][yy].parent_area.x0; + if (stride == 1 && pvt->tcm_map + [xx][yy].type == TCM_2D) { + xx = pvt->tcm_map + [xx][yy].parent_area.p0.x; P3("Moving to parent location start_x\ (%d %d)\n", xx, yy); } @@ -643,8 +734,8 @@ s32 scan_r2l_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, } /*Now if we are here it implies we have potential candidates*/ - ret = select_candidate(w, h, num_short_listed, short_listed, scan_area, - g_scan_criteria_r2l_b2t, alloc_area); + ret = select_candidate(tcm, w, h, num_short_listed, short_listed, + scan_area, g_scan_criteria_r2l_b2t, alloc_area); if (ret != TilerErrorNone) PE("Error in Selecting a Candidate\n"); @@ -655,8 +746,7 @@ s32 scan_r2l_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, return ret; } - - +#endif /** * @description: raster scan left to right from top to bottom; find if there is @@ -672,36 +762,36 @@ s32 scan_r2l_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, * the 'alloc_area' area contains TL and BR corners of the allocated area * */ - -s32 scan_l2r_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, - struct area_spec *alloc_area) +s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 stride, + struct tcm_area *scan_area, struct tcm_area *alloc_area) { + s32 ret = TilerErrorNone; s32 xx = 0, yy = 0; s16 start_x = -1, end_x = -1, start_y = -1, end_y = -1; s16 found_x = -1, found_y = -1; u16 remainder; struct area_spec_list *short_listed = NULL; - struct area_spec candidate_area = {0, 0, 0, 0}; + struct tcm_area candidate_area; u16 num_short_listed = 0; - s32 ret = TilerErrorNone; - + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; + memset(&candidate_area, 0, sizeof(struct tcm_area)); P2("Scanning From Left 2 Right Top 2 Bottom, ScanArea: %s\n", - AREA_STR(a_str, scan_area)); + AREA_STR(a_str, scan_area)); - start_x = scan_area->x0; - end_x = scan_area->x1; - start_y = scan_area->y0; - end_y = scan_area->y1; + start_x = scan_area->p0.x; + end_x = scan_area->p1.x; + start_y = scan_area->p0.y; + end_y = scan_area->p1.y; /*Basic checks */ - if (scan_area == NULL || alloc_area == NULL) { + if (scan_area == NULL || alloc_area == NULL || tcm == NULL) { PE("Null value found\n"); return TilerErrorInvalidArg; } /*Check if the scan area co-ordinates are valid */ - if ((scan_area->x1 < scan_area->x0) || - (scan_area->y1 < scan_area->y0)) { + if ((scan_area->p1.x < scan_area->p0.x) || + (scan_area->p1.y < scan_area->p0.y)) { PE("Invalid scan area: %s\n", AREA_STR(a_str, scan_area)); return TilerErrorInvalidScanArea; } @@ -744,18 +834,19 @@ s32 scan_l2r_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, for (yy = start_y; yy <= end_y; ++yy) { for (xx = start_x; xx <= end_x; xx += stride) { /* if NOT occupied */ - if (g_area_container[xx][yy].is_occupied == - NOT_OCCUPIED) { - if (FIT == check_fit_r_and_b(w, h, xx, yy)) { + if (pvt->tcm_map[xx][yy].is_occupied == + NOT_OCCUPIED) { + if (check_fit_r_and_b(tcm, w, h, xx, yy) + == FIT) { P3("Found Free Shoulder at: (%d, %d)\n", - xx, yy); + xx, yy); found_x = xx; found_y = yy; /* Insert this candidate, it is just a co-ordinate, reusing Area */ assign(&candidate_area, xx, yy, 0, 0); insert_element(&short_listed, - &candidate_area, TWO_D); + &candidate_area, TCM_2D); num_short_listed++; /*changing upper bound on x direction */ #ifdef X_SCAN_LIMITER @@ -766,10 +857,10 @@ s32 scan_l2r_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, } else { /* Optimization required only for Non Aligned, Aligned anyways skip by 32/64 tiles at a time */ - if (stride == 1 && g_area_container - [xx][yy].type == TWO_D) { - xx = g_area_container - [xx][yy].parent_area.x1; + if (stride == 1 && pvt->tcm_map + [xx][yy].type == TCM_2D) { + xx = pvt->tcm_map + [xx][yy].parent_area.p1.x; P3("Moving to parent location end_x\ (%d %d)\n", xx, yy); } @@ -788,20 +879,19 @@ s32 scan_l2r_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, PE("No candidates found in a given scan area\n"); return TilerErrorNoRoom; } - /*Now if we are here it implies we have potential candidates*/ - ret = select_candidate(w, h, num_short_listed, short_listed, scan_area, - g_scan_criteria_l2r_t2b, alloc_area); + ret = select_candidate(tcm, w, h, num_short_listed, short_listed, + scan_area, g_scan_criteria_l2r_t2b, alloc_area); if (ret != TilerErrorNone) PE("Error in Selecting a Candidate\n"); /*Just clean up resources */ clean_list(&short_listed); - /* dump_list_entries(short_listed); */ return ret; } +#ifdef SCAN_BOTTOM_UP /** * @description: raster scan left to right from bottom to top; find if there is * a free area to fit a given w x h inside the 'scan area'. If there is a free @@ -816,35 +906,36 @@ s32 scan_l2r_t2b(u16 w, u16 h, u16 stride, struct area_spec *scan_area, * the 'alloc_area' area contains TL and BR corners of the allocated area * */ -s32 scan_l2r_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, - struct area_spec *alloc_area) +static s32 scan_l2r_b2t(struct tcm *tcm, u16 w, u16 h, u16 stride, + struct tcm_area *scan_area, struct tcm_area *alloc_area) { + s32 ret = TilerErrorNone; s32 xx = 0, yy = 0; s16 start_x = -1, end_x = -1, start_y = -1, end_y = -1; s16 found_x = -1, found_y = -1; u16 remainder; struct area_spec_list *short_listed = NULL; - struct area_spec candidate_area = {0, 0, 0, 0}; + struct tcm_area candidate_area; u16 num_short_listed = 0; - s32 ret = TilerErrorNone; - + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; + memset(&candidate_area, 0, sizeof(struct tcm_area)); P2("Scanning From Left 2 Right Bottom 2 Top, ScanArea: %s\n", - AREA_STR(a_str, scan_area)); + AREA_STR(a_str, scan_area)); - start_x = scan_area->x0; - end_x = scan_area->x1; - start_y = scan_area->y0; - end_y = scan_area->y1; + start_x = scan_area->p0.x; + end_x = scan_area->p1.x; + start_y = scan_area->p0.y; + end_y = scan_area->p1.y; /*Basic checks */ - if (scan_area == NULL || alloc_area == NULL) { + if (scan_area == NULL || alloc_area == NULL || tcm == NULL) { PE("Null value found\n"); return TilerErrorInvalidArg; } /*Check if the scan area co-ordinates are valid */ - if ((scan_area->x1 < scan_area->x0) || - (scan_area->y0 < scan_area->y1)) { + if ((scan_area->p1.x < scan_area->p0.x) || + (scan_area->p0.y < scan_area->p1.y)) { PE("Invalid scan area: %s\n", AREA_STR(a_str, scan_area)); return TilerErrorInvalidScanArea; } @@ -878,7 +969,7 @@ s32 scan_l2r_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, /* Just updating start and ends */ P2(" stride : %d\n, start_x : %d end_x : %d start_y : %d end_y : %d\n", - stride, start_x, end_x, start_y, end_y); + stride, start_x, end_x, start_y, end_y); /* Start scanning: These scans are always inclusive ones so if we are given a start x = 0 is a valid value so if we have a end_x = 255, @@ -887,17 +978,18 @@ s32 scan_l2r_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, for (yy = start_y; yy >= end_y; --yy) { for (xx = start_x; xx <= end_x; xx += stride) { /* if NOT occupied */ - if (!g_area_container[xx][yy].is_occupied) { - if (check_fit_r_and_b(w, h, xx, yy) == FIT) { + if (!pvt->tcm_map[xx][yy].is_occupied) { + if (check_fit_r_and_b(tcm, w, h, xx, yy) + == FIT) { P3("Found Free Shoulder at: (%d, %d)\n", - xx, yy); + xx, yy); found_x = xx; found_y = yy; /* Insert this candidate, it is just a co-ordinate, reusing Area */ assign(&candidate_area, xx, yy, 0, 0); insert_element(&short_listed, - &candidate_area, TWO_D); + &candidate_area, TCM_2D); num_short_listed++; /*changing upper bound on x direction */ #ifdef X_SCAN_LIMITER @@ -908,10 +1000,10 @@ s32 scan_l2r_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, } else { /* Optimization required only for Non Aligned, Aligned anyways skip by 32/64 tiles at a time */ - if (stride == 1 && g_area_container - [xx][yy].type == TWO_D) { - xx = g_area_container - [xx][yy].parent_area.x1; + if (stride == 1 && pvt->tcm_map + [xx][yy].type == TCM_2D) { + xx = pvt->tcm_map + [xx][yy].parent_area.p1.x; P3("Moving to parent location end_x\ (%d %d)\n", xx, yy); } @@ -933,8 +1025,8 @@ s32 scan_l2r_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, } /*Now if we are here it implies we have potential candidates*/ - ret = select_candidate(w, h, num_short_listed, short_listed, scan_area, - g_scan_criteria_l2r_b2t, alloc_area); + ret = select_candidate(tcm, w, h, num_short_listed, short_listed, + scan_area, g_scan_criteria_l2r_b2t, alloc_area); if (ret != TilerErrorNone) PE("Error in Selecting a Candidate\n"); @@ -944,12 +1036,12 @@ s32 scan_l2r_b2t(u16 w, u16 h, u16 stride, struct area_spec *scan_area, /* dump_list_entries(short_listed); */ return ret; } - +#endif /* -Note: In General the cordinates specified in the scan area area relavent to the -scan sweep directions. i.e A scan Area from Top Left Corner will have x0 <= x1 -and y0 <= y1. Where as A scan Area from bottom Right Corner will have x1 <= x0 -and y1 <= y0 +Note: In General the cordinates specified in the scan area area relevant to the +scan sweep directions. i.e A scan Area from Top Left Corner will have +p0.x <= p1.x and p0.y <= p1.y. Where as A scan Area from bottom Right Corner +will have p1.x <= p0.x and p1.y <= p0.y */ /** @@ -965,34 +1057,35 @@ and y1 <= y0 * the 'alloc_area' area contains start and end tile (inclusive). * */ -s32 scan_r2l_b2t_one_dim(u32 num_of_pages, struct area_spec *scan_area, - struct area_spec *alloc_area) +s32 scan_r2l_b2t_one_dim(struct tcm *tcm, u32 num_of_pages, + struct tcm_area *scan_area, struct tcm_area *alloc_area) { + s32 fit = NO_FIT; + s32 ret = TilerErrorNone; u16 x, y; u16 left_x, left_y, busy_x, busy_y; - s32 ret = TilerErrorNone; - s32 fit = NO_FIT; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; /*Basic checks */ - if (scan_area == NULL || alloc_area == NULL) { + if (scan_area == NULL || alloc_area == NULL || tcm == NULL) { PE("Null arguments found\n"); return TilerErrorInvalidArg; } - if (scan_area->y0 < scan_area->y1) { + if (scan_area->p0.y < scan_area->p1.y) { PE("Invalid scan area: %s\n", AREA_STR(a_str, scan_area)); return TilerErrorInvalidScanArea; } P2("Scanning From Right 2 Left Bottom 2 Top for 1D: ScanArea: %s\n", - AREA_STR(a_str, scan_area)); + AREA_STR(a_str, scan_area)); /* Note: Checking sanctity of scan area * The reason for checking this that 1D allocations assume that the X ranges the entire TilerSpace X ie ALL Columns * The scan area can limit only the Y ie, Num of Rows for 1D allocation. We also expect we could have only 1 row for 1D allocation - * i.e our scan_area y0 and y1 may have a same value. + * i.e our scan_area p0.y and p1.y may have a same value. */ /* @@ -1000,49 +1093,48 @@ s32 scan_r2l_b2t_one_dim(u32 num_of_pages, struct area_spec *scan_area, Can't i just ignore X and then take the u16 (Y dimension) and assume X to range from MAX_X_DIMEN to 0 ?? */ - if (MAX_X_DIMMENSION != (1 + (scan_area->x0 - scan_area->x1))) { + if (pvt->width != (1 + (scan_area->p0.x - scan_area->p1.x))) { PE("Not a valid Scan Area, for 1D the width should be entire\ Tiler u16 (%d) but it is (%d)\n", - MAX_X_DIMMENSION, 1 + (scan_area->x0 - scan_area->x1)); + pvt->width, 1 + (scan_area->p0.x - scan_area->p1.x)); return TilerErrorInvalidDimension; } /* checking if scan area can accomodate the num_of_pages */ - if (num_of_pages > MAX_X_DIMMENSION * INCL_LEN(scan_area->y0, - scan_area->y1)) { + if (num_of_pages > pvt->width * INCL_LEN(scan_area->p0.y, + scan_area->p1.y)) { PE("Num of Pages exceed Max possible (%d) for a given scan area\ - %s\n", MAX_X_DIMMENSION *\ - (scan_area->y0 - scan_area->y1), - AREA_STR(a_str, scan_area)); + %s\n", pvt->width * (scan_area->p0.y - scan_area->p1.y), + AREA_STR(a_str, scan_area)); return TilerErrorNoRoom; } /* Ah we are here, it implies we can try fitting now after we have checked everything */ - left_x = scan_area->x0; - left_y = scan_area->y0; + left_x = scan_area->p0.x; + left_y = scan_area->p0.y; while (ret == TilerErrorNone) { x = left_x; y = left_y; /* P("Checking if (%d %d) is Occupied\n",x,y); */ - if (g_area_container[x][y].is_occupied == NOT_OCCUPIED) { - ret = move_left(x, y, (num_of_pages - 1), - &left_x, &left_y); + if (pvt->tcm_map[x][y].is_occupied == NOT_OCCUPIED) { + ret = move_left(tcm, x, y, (num_of_pages - 1), + &left_x, &left_y); if (ret == TilerErrorNone) { P3("Moved left to (%d %d) for num_of_pages (%d)\ ,checking for fit\n", left_x, - left_y, (num_of_pages - 1)); - fit = check_fit_r_one_dim(left_x, left_y, - num_of_pages, &busy_x, &busy_y); + left_y, (num_of_pages - 1)); + fit = check_fit_r_one_dim(tcm, left_x, left_y, + num_of_pages, &busy_x, &busy_y); if (fit == FIT) { /*Implies we are fine, we found a place to put our 1D alloc */ assign(alloc_area, left_x, left_y, - busy_x, busy_y); + busy_x, busy_y); P3("Allocated 1D area: %s\n", - AREA_STR(a_str, alloc_area)); + AREA_STR(a_str, alloc_area)); break; } else { /* Implies it did not fit, the busy_x, @@ -1060,11 +1152,11 @@ s32 scan_r2l_b2t_one_dim(u32 num_of_pages, struct area_spec *scan_area, /* Ah if we are here then we the Tile is occupied, now we might move to the start of parent locations */ - if (g_area_container[x][y].type == ONE_D) { - busy_x = g_area_container[x][y].parent_area.x0; - busy_y = g_area_container[x][y].parent_area.y0; + if (pvt->tcm_map[x][y].type == TCM_1D) { + busy_x = pvt->tcm_map[x][y].parent_area.p0.x; + busy_y = pvt->tcm_map[x][y].parent_area.p0.y; } else { - busy_x = g_area_container[x][y].parent_area.x0; + busy_x = pvt->tcm_map[x][y].parent_area.p0.x; busy_y = y; } x = busy_x; @@ -1072,10 +1164,9 @@ s32 scan_r2l_b2t_one_dim(u32 num_of_pages, struct area_spec *scan_area, P3("Busy Tile found moving to ParentArea start :\ (%d %d)\n", x, y); - ret = move_left(x, y, 1, &left_x, &left_y); + ret = move_left(tcm, x, y, 1, &left_x, &left_y); } - if (!fit) ret = TilerErrorNoRoom; @@ -1097,107 +1188,118 @@ s32 scan_r2l_b2t_one_dim(u32 num_of_pages, struct area_spec *scan_area, * * */ -s32 scan_areas_and_find_fit(u16 w, u16 h, u16 stride, - struct area_spec *allocated_area) +s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 stride, + struct tcm_area *allocated_area) { + s32 ret = TilerErrorGeneral; /* Checking for input arguments */ /* No need to do this check, we have checked it in the parent call */ - struct area_spec scan_area = {0, 0, 0, 0}; - s32 ret = TilerErrorGeneral; + struct tcm_area scan_area; u16 boundary_x = 0, boundary_y = 0; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; s32 need_scan_flag = 2; + memset(&scan_area, 0, sizeof(struct tcm_area)); - if (stride == 64) { - boundary_x = g_div_ln_btw_64_and_32_align.x1 - 1; - boundary_y = g_div_ln_btw_64_and_32_align.y1 - 1; + if (stride == 64 || stride == 32) { + boundary_x = pvt->div_pt.x - 1; + boundary_y = pvt->div_pt.y - 1; /* more intelligence here */ - if (w > g_div_ln_btw_64_and_32_align.x1) { - boundary_x = MAX_X_DIMMENSION - 1; + if (w > pvt->div_pt.x) { + boundary_x = pvt->width - 1; --need_scan_flag; } - if (h > g_div_ln_btw_64_and_32_align.y1) { - boundary_y = MAX_Y_DIMMENSION - 1; + if (h > pvt->div_pt.y) { + boundary_y = pvt->height - 1; --need_scan_flag; } assign(&scan_area, 0, 0, boundary_x, boundary_y); - ret = scan_l2r_t2b(w, h, stride, &scan_area, allocated_area); - + ret = scan_l2r_t2b(tcm, w, h, stride, &scan_area, + allocated_area); if (ret != TilerErrorNone && need_scan_flag) { /*Fall back Scan the entire Tiler area*/ - assign(&scan_area, 0, 0, MAX_X_DIMMENSION - 1, - MAX_Y_DIMMENSION - 1); - ret = scan_l2r_t2b(w, h, stride, &scan_area, - allocated_area); + assign(&scan_area, 0, 0, pvt->width - 1, + pvt->height - 1); + ret = scan_l2r_t2b(tcm, w, h, stride, &scan_area, + allocated_area); } - } else if (stride == 32) { + } else if (stride == 1) { - boundary_x = g_div_ln_btw_64_and_32_align.x1; - boundary_y = g_div_ln_btw_64_and_32_align.y1-1; + boundary_x = pvt->div_pt.x; + boundary_y = pvt->div_pt.y-1; /* more intelligence here */ - if (w > (MAX_X_DIMMENSION - g_div_ln_btw_64_and_32_align.x1)) { + if (w > (pvt->width - pvt->div_pt.x)) { boundary_x = 0; --need_scan_flag; } - if (h > g_div_ln_btw_64_and_32_align.y1) { - boundary_y = MAX_Y_DIMMENSION - 1; + if (h > pvt->div_pt.y) { + boundary_y = pvt->height - 1; --need_scan_flag; } - assign(&scan_area, MAX_X_DIMMENSION - 1, 0, boundary_x, - boundary_y); - ret = scan_r2l_t2b(w, h, stride, &scan_area, allocated_area); + assign(&scan_area, pvt->width - 1, 0, boundary_x, + boundary_y); + ret = scan_r2l_t2b(tcm, w, h, stride, &scan_area, + allocated_area); if (ret != TilerErrorNone && need_scan_flag) { /*Fall back Scan the entire Tiler area*/ - assign(&scan_area, MAX_X_DIMMENSION - 1, 0, 0, - MAX_Y_DIMMENSION - 1); - ret = scan_r2l_t2b(w, h, stride, &scan_area, - allocated_area); + assign(&scan_area, pvt->width - 1, 0, 0, + pvt->height - 1); + ret = scan_r2l_t2b(tcm, w, h, stride, &scan_area, + allocated_area); } - } else if (stride == 1) { + } + + /* March 30th: As per discussion: Moved 64 and 32 to left of Container + * and Align None to right of container. + */ +#if 0 + else if (stride == 1) { /*The reason we use 64-Align area is because we dont want to grow down and reduced 1D space */ - if (h > g_div_ln_btw_64_and_32_align.y1) { + if (h > pvt->div_pt.y) { need_scan_flag -= 2; - assign(&scan_area, 0, 0, MAX_X_DIMMENSION - 1, - MAX_Y_DIMMENSION - 1); - ret = scan_l2r_t2b(w, h, stride, &scan_area, - allocated_area); + assign(&scan_area, 0, 0, pvt->width - 1, + pvt->height - 1); + ret = scan_l2r_t2b(tcm, w, h, stride, &scan_area, + allocated_area); } else { assign(&scan_area, 0, - g_div_ln_btw_64_and_32_align.y1 - 1, - MAX_X_DIMMENSION - 1, 0); - /*Scans Up in 64 and 32 areas accross the whole width */ - ret = scan_l2r_b2t(w, h, stride, &scan_area, - allocated_area); + pvt->div_pt.y - 1, + pvt->width - 1, 0); + /*Scans Up in 64 and 32 areas accross the whole width*/ + ret = scan_l2r_b2t(tcm, w, h, stride, &scan_area, + allocated_area); } if (ret != TilerErrorNone && need_scan_flag) { - assign(&scan_area, 0, 0, MAX_X_DIMMENSION - 1, - MAX_Y_DIMMENSION - 1); - ret = scan_l2r_t2b(w, h, stride, &scan_area, - allocated_area); + assign(&scan_area, 0, 0, pvt->width - 1, + pvt->height - 1); + ret = scan_l2r_t2b(tcm, w, h, stride, &scan_area, + allocated_area); } } - +#endif return ret; } - -s32 check_fit_r_and_b(u16 w, u16 h, u16 left_x, u16 top_y) +s32 check_fit_r_and_b(struct tcm *tcm, u16 w, u16 h, u16 left_x, + u16 top_y) { u16 xx = 0, yy = 0; s32 ret = FIT; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; + for (yy = top_y; yy < top_y+h; ++yy) { for (xx = left_x; xx < left_x+w; ++xx) { /*P("Checking Occ: (%d %d) - %d\n",xx,yy, - g_area_container[xx][yy].is_occupied); */ - if (g_area_container[xx][yy].is_occupied == OCCUPIED) { + pvt->tcm_map[xx][yy].is_occupied); */ + if (pvt->tcm_map[xx][yy].is_occupied == OCCUPIED) { ret = NO_FIT; return ret; } @@ -1206,20 +1308,20 @@ s32 check_fit_r_and_b(u16 w, u16 h, u16 left_x, u16 top_y) return ret; } -s32 check_fit_r_one_dim(u16 x, u16 y, u32 num_of_pages, u16 *busy_x, - u16 *busy_y) +s32 check_fit_r_one_dim(struct tcm *tcm, u16 x, u16 y, u32 num_of_pages, + u16 *busy_x, u16 *busy_y) { s32 fit = FIT; s32 ret = TilerErrorNone; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; s32 i = 0; - *busy_x = x; *busy_y = y; P2("checking Fit for (%d) pages from (%d %d)\n ", num_of_pages, x, y); while (i < num_of_pages) { /* P("Checking if occupied (%d %d)\n",x, y); */ - if (g_area_container[x][y].is_occupied) { + if (pvt->tcm_map[x][y].is_occupied) { /*Oh the Tile is occupied so we break and let know that we encoutered a BUSY tile */ fit = NO_FIT; @@ -1227,16 +1329,15 @@ s32 check_fit_r_one_dim(u16 x, u16 y, u32 num_of_pages, u16 *busy_x, /* Now going to the start of the parent allocation so we avoid unecessary checking */ - if (g_area_container[x][y].type == ONE_D) { - *busy_x = g_area_container[x][y].parent_area.x0; - *busy_y = g_area_container[x][y].parent_area.y0; + if (pvt->tcm_map[x][y].type == TCM_1D) { + *busy_x = pvt->tcm_map[x][y].parent_area.p0.x; + *busy_y = pvt->tcm_map[x][y].parent_area.p0.y; } else { - *busy_x = g_area_container[x][y].parent_area.x0; + *busy_x = pvt->tcm_map[x][y].parent_area.p0.x; *busy_y = y; } /* To Do: */ - /*Could also move left in case of TWO_D*/ - + /*Could also move left in case of TCM_2D*/ P2("Busy Tile found moving to ParentArea start :\ (%d %d)\n", *busy_x, *busy_y); break; @@ -1250,7 +1351,7 @@ s32 check_fit_r_one_dim(u16 x, u16 y, u32 num_of_pages, u16 *busy_x, if (i == num_of_pages) break; - ret = move_right(x, y, 1, busy_x, busy_y); + ret = move_right(tcm, x, y, 1, busy_x, busy_y); if (ret != TilerErrorNone) { PE("Error in Moving Right.. Breaking...\n"); fit = NO_FIT; @@ -1265,33 +1366,35 @@ s32 check_fit_r_one_dim(u16 x, u16 y, u32 num_of_pages, u16 *busy_x, } - - -s32 insert_area_with_tiler_page(struct area_spec *area, struct tiler_page tile) +s32 insert_area_with_tiler_page(struct tcm *tcm, + struct tcm_area *area, struct tiler_page tile) { s32 x, y; - if (area->x0 < 0 || area->x1 >= MAX_X_DIMMENSION || area->y0 < 0 || - area->y1 >= MAX_Y_DIMMENSION) { + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; + if (area->p0.x < 0 || area->p1.x >= pvt->width || area->p0.y < 0 || + area->p1.y >= pvt->height) { PE("Invalid dimensions\n"); return TilerErrorInvalidDimension; } - P2("Inserting Tiler Page at (%d %d) (%d %d)\n", area->x0, area->y0, - area->x1, area->y1); + P2("Inserting Tiler Page at (%d %d) (%d %d)\n", area->p0.x, area->p0.y, + area->p1.x, area->p1.y); /*If you are here: basic checks are done */ - for (x = area->x0; x <= area->x1; ++x) - for (y = area->y0; y <= area->y1; ++y) - g_area_container[x][y] = tile; + for (x = area->p0.x; x <= area->p1.x; ++x) + for (y = area->p0.y; y <= area->p1.y; ++y) + pvt->tcm_map[x][y] = tile; return TilerErrorNone; } - -s32 insert_pages_with_tiler_page(struct area_spec *area, struct tiler_page tile) +s32 insert_pages_with_tiler_page(struct tcm *tcm, struct tcm_area *area, + struct tiler_page tile) { u16 x = 0, y = 0; u16 right_x = 0, right_y = 0; s32 ret = TilerErrorNone; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; + if (area == NULL) { PE("Null input received\n"); return TilerErrorInvalidArg; @@ -1302,16 +1405,17 @@ s32 insert_pages_with_tiler_page(struct area_spec *area, struct tiler_page tile) *Do i really need to check integrity of area specs? */ - P2("Inserting Tiler Pages from (%d %d) to (%d %d)\n", area->x0, - area->y0, area->x1, area->y1); + P2("Inserting Tiler Pages from (%d %d) to (%d %d)\n", area->p0.x, + area->p0.y, area->p1.x, area->p1.y); + + x = area->p0.x; + y = area->p0.y; - x = area->x0; - y = area->y0; - while (!(x == area->x1 && y == area->y1)) { + while (!(x == area->p1.x && y == area->p1.y)) { /* P("(%d %d)\n",x,y); */ - g_area_container[x][y] = tile; - ret = move_right(x, y, 1, &right_x, &right_y); + pvt->tcm_map[x][y] = tile; + ret = move_right(tcm, x, y, 1, &right_x, &right_y); if (ret == TilerErrorNone) { x = right_x; y = right_y; @@ -1321,24 +1425,27 @@ s32 insert_pages_with_tiler_page(struct area_spec *area, struct tiler_page tile) } } /*Of course since this is inclusive we need to set the last tile too */ - g_area_container[x][y] = tile; + pvt->tcm_map[x][y] = tile; + return TilerErrorNone; } -static s32 select_candidate(IN u16 w, IN u16 h, IN u16 num_short_listed, - IN struct area_spec_list *short_listed, IN struct area_spec *scan_area, - IN s32 criteria, OUT struct area_spec *alloc_area) +s32 select_candidate(struct tcm *tcm, u16 w, u16 h, + u16 num_short_listed, struct area_spec_list *short_listed, + struct tcm_area *scan_area, s32 criteria, + struct tcm_area *alloc_area) { + /* book keeping the winner */ struct area_spec_list *win_candidate = NULL; - struct nearness_factor win_near_factor = {0.0, 0.0}; + struct nearness_factor win_near_factor = {0, 0}; struct neighbour_stats win_neigh_stats = {0, 0, 0, 0, 0, 0, 0, 0}; u16 win_total_neighs = 0; /*book keeping the current one being evaluated */ struct area_spec_list *cur_candidate = NULL; - struct area_spec *cur_area = NULL; - struct nearness_factor cur_near_factor = {0.0, 0.0}; + struct tcm_area *cur_area = NULL; + struct nearness_factor cur_near_factor = {0, 0}; struct neighbour_stats cur_neigh_stats = {0, 0, 0, 0, 0, 0, 0, 0}; u16 cur_total_neighs = 0; @@ -1359,8 +1466,9 @@ static s32 select_candidate(IN u16 w, IN u16 h, IN u16 num_short_listed, * one place where the selection is made. Here I am returning the first one */ - assign(alloc_area, short_listed->area.x0, short_listed->area.y0, - short_listed->area.x0 + w - 1, short_listed->area.y0 + h - 1); + assign(alloc_area, short_listed->area.p0.x, + short_listed->area.p0.y, short_listed->area.p0.x + w - 1, + short_listed->area.p0.y + h - 1); return TilerErrorNone; } @@ -1371,8 +1479,9 @@ static s32 select_candidate(IN u16 w, IN u16 h, IN u16 num_short_listed, * be the same as if selecting the Horizontal one. */ if (criteria & CR_FIRST_FOUND || criteria & CR_BIAS_HORIZONTAL) { - assign(alloc_area, short_listed->area.x0, short_listed->area.y0, - short_listed->area.x0 + w - 1, short_listed->area.y0 + h - 1); + assign(alloc_area, short_listed->area.p0.x, + short_listed->area.p0.y, short_listed->area.p0.x + w - 1, + short_listed->area.p0.y + h - 1); return TilerErrorNone; } @@ -1380,9 +1489,9 @@ static s32 select_candidate(IN u16 w, IN u16 h, IN u16 num_short_listed, replace with the one who has better credentials w/ to the criteria */ win_candidate = short_listed; - get_busy_neigh_stats(w, h, &short_listed->area, &win_neigh_stats); + get_busy_neigh_stats(tcm, w, h, &short_listed->area, &win_neigh_stats); win_total_neighs = TOTAL_BOUNDARY(&win_neigh_stats) + - TOTAL_OCCUPIED(&win_neigh_stats); + TOTAL_OCCUPIED(&win_neigh_stats); get_nearness_factor(scan_area, &short_listed->area, &win_near_factor); /* now check from second candidate onwards */ cur_candidate = short_listed->next; @@ -1393,11 +1502,11 @@ static s32 select_candidate(IN u16 w, IN u16 h, IN u16 num_short_listed, * all of them in all Criteria, but makes simpler code */ cur_area = &cur_candidate->area; - get_busy_neigh_stats(w, h, cur_area, &cur_neigh_stats); + get_busy_neigh_stats(tcm, w, h, cur_area, &cur_neigh_stats); get_nearness_factor(scan_area, cur_area, &cur_near_factor); /* Check against the winner, if this one is better */ cur_total_neighs = TOTAL_BOUNDARY(&cur_neigh_stats) + - TOTAL_OCCUPIED(&cur_neigh_stats); + TOTAL_OCCUPIED(&cur_neigh_stats); @@ -1413,12 +1522,12 @@ static s32 select_candidate(IN u16 w, IN u16 h, IN u16 num_short_listed, */ if (criteria & CR_BIAS_VERTICAL) { P("cur distance :%d win distance: %d\n", - INCL_LEN_MOD(cur_area->y0, scan_area->y0), - INCL_LEN_MOD(win_candidate->area.y0, - scan_area->y0)) - if (INCL_LEN_MOD(cur_area->y0, scan_area->y0) > - INCL_LEN_MOD(win_candidate->area.y0, - scan_area->y0)) { + INCL_LEN_MOD(cur_area->p0.y, scan_area->p0.y), + INCL_LEN_MOD(win_candidate->area.p0.y, + scan_area->p0.y)) + if (INCL_LEN_MOD(cur_area->p0.y, scan_area->p0.y) > + INCL_LEN_MOD(win_candidate->area.p0.y, + scan_area->p0.y)) { swap_flag = YES; } } @@ -1428,24 +1537,24 @@ static s32 select_candidate(IN u16 w, IN u16 h, IN u16 num_short_listed, /* Check against the winner, if this one is better */ cur_total_neighs = TOTAL_BOUNDARY(&cur_neigh_stats) + - TOTAL_OCCUPIED(&cur_neigh_stats); + TOTAL_OCCUPIED(&cur_neigh_stats); if (win_total_neighs <= cur_total_neighs) { P3("Logic: Oh win_total_neighs(%d) <=\ cur_total_neighs(%d)\n", - win_total_neighs, cur_total_neighs); + win_total_neighs, cur_total_neighs); if (win_total_neighs < cur_total_neighs || (TOTAL_OCCUPIED(&win_neigh_stats) < - TOTAL_OCCUPIED(&cur_neigh_stats))) { + TOTAL_OCCUPIED(&cur_neigh_stats))) { P3("Logic: Found one with more\ neighbours win_total_neighs:%d\ cur_total_neighs:%d WinOcc: %d,\ CurOcc: %d\n", win_total_neighs, - cur_total_neighs, - TOTAL_OCCUPIED( - &win_neigh_stats), - TOTAL_OCCUPIED( - &cur_neigh_stats)); + cur_total_neighs, + TOTAL_OCCUPIED( + &win_neigh_stats), + TOTAL_OCCUPIED( + &cur_neigh_stats)); swap_flag = YES; } else if ((TOTAL_OCCUPIED(&win_neigh_stats) == TOTAL_OCCUPIED(&cur_neigh_stats))) { @@ -1456,21 +1565,21 @@ static s32 select_candidate(IN u16 w, IN u16 h, IN u16 num_short_listed, /*Now we check the nearness factor */ P3("Logic: Ah WinOcc(%d) == CurOcc:\ (%d), so checking Nearness factor\n", - TOTAL_OCCUPIED(&win_neigh_stats), - TOTAL_OCCUPIED(&cur_neigh_stats)); + TOTAL_OCCUPIED(&win_neigh_stats), + TOTAL_OCCUPIED(&cur_neigh_stats)); P3("Logic: Hmm winNF (%3f) & curNF\ (%3f)\n", - (double)(win_near_factor.nf_x - + win_near_factor.nf_y), - (double)(cur_near_factor.nf_x - + cur_near_factor.nf_y)); + (double)(win_near_factor.nf_x + + win_near_factor.nf_y), + (double)(cur_near_factor.nf_x + + cur_near_factor.nf_y)); if ((s32)(win_near_factor.nf_x + win_near_factor.nf_y) > (s32)(cur_near_factor.nf_x + cur_near_factor.nf_y)) { P3("Logic: So, nearness factor\ - of Cur is <\ - than Win\n"); + of Cur is <\ + than Win\n"); swap_flag = YES; } @@ -1498,25 +1607,31 @@ static s32 select_candidate(IN u16 w, IN u16 h, IN u16 num_short_listed, } - assign(alloc_area, win_candidate->area.x0, win_candidate->area.y0, - win_candidate->area.x0+w - 1, win_candidate->area.y0 + h - 1); + assign(alloc_area, win_candidate->area.p0.x, win_candidate->area.p0.y, + win_candidate->area.p0.x+w - 1, + win_candidate->area.p0.y + h - 1); + return TilerErrorNone; } -s32 get_nearness_factor(struct area_spec *scan_area, - struct area_spec *candidate, struct nearness_factor *nf) +s32 get_nearness_factor(struct tcm_area *scan_area, + struct tcm_area *candidate, struct nearness_factor *nf) { + if (nf == NULL || scan_area == NULL || candidate == NULL) { PE("NULL input found\n"); return TilerErrorInvalidArg; } /* For the following calculation we need worry of +/- sign, the - relative distances take of this */ - nf->nf_x = (s32)(candidate->x0 - scan_area->x0)/ - (scan_area->x1 - scan_area->x0); - nf->nf_y = (s32)(candidate->y0 - scan_area->y0)/ - (scan_area->y1 - scan_area->y0); + relative distances take of this. Multiplied by 1000, there + is no floating point arithmetic used in kernel */ + + nf->nf_x = (s32)(candidate->p0.x - scan_area->p0.x)*1000/ + (scan_area->p1.x - scan_area->p0.x); + nf->nf_y = (s32)(candidate->p0.y - scan_area->p0.y)*1000/ + (scan_area->p1.y - scan_area->p0.y); + return TilerErrorNone; } @@ -1529,14 +1644,17 @@ s32 get_nearness_factor(struct area_spec *scan_area, _ |______________|_ |<-----B------>| */ -s32 get_busy_neigh_stats(u16 width, u16 height, -struct area_spec *top_left_corner, struct neighbour_stats *neighbour_stat) + +s32 get_busy_neigh_stats(struct tcm *tcm, u16 width, u16 height, + struct tcm_area *top_left_corner, + struct neighbour_stats *neighbour_stat) { s16 xx = 0, yy = 0; - struct area_spec left_edge; - struct area_spec right_edge; - struct area_spec top_edge; - struct area_spec bottom_edge; + struct tcm_area left_edge; + struct tcm_area right_edge; + struct tcm_area top_edge; + struct tcm_area bottom_edge; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; if (neighbour_stat == NULL) { PE("Null input received\n"); @@ -1552,23 +1670,24 @@ struct area_spec *top_left_corner, struct neighbour_stats *neighbour_stat) memset(neighbour_stat, 0, sizeof(struct neighbour_stats)); /* Finding Top Edge */ - assign(&top_edge, top_left_corner->x0, top_left_corner->y0, - top_left_corner->x0 + width - 1, top_left_corner->y0); + assign(&top_edge, top_left_corner->p0.x, top_left_corner->p0.y, + top_left_corner->p0.x + width - 1, top_left_corner->p0.y); /* Finding Bottom Edge */ - assign(&bottom_edge, top_left_corner->x0, - top_left_corner->y0+height - 1, - top_left_corner->x0 + width - 1, - top_left_corner->y0 + height - 1); + assign(&bottom_edge, top_left_corner->p0.x, + top_left_corner->p0.y+height - 1, + top_left_corner->p0.x + width - 1, + top_left_corner->p0.y + height - 1); /* Finding Left Edge */ - assign(&left_edge, top_left_corner->x0, top_left_corner->y0, - top_left_corner->x0, top_left_corner->y0 + height - 1); + assign(&left_edge, top_left_corner->p0.x, top_left_corner->p0.y, + top_left_corner->p0.x, top_left_corner->p0.y + height - 1); /* Finding Right Edge */ - assign(&right_edge, top_left_corner->x0 + width - 1, - top_left_corner->y0, - top_left_corner->x0 + width - 1, top_left_corner->y0 + height - 1); + assign(&right_edge, top_left_corner->p0.x + width - 1, + top_left_corner->p0.y, + top_left_corner->p0.x + width - 1, + top_left_corner->p0.y + height - 1); /* dump_area(&top_edge); dump_area(&right_edge); @@ -1577,90 +1696,217 @@ struct area_spec *top_left_corner, struct neighbour_stats *neighbour_stat) */ /*Parsing through top & bottom edge*/ - for (xx = top_edge.x0; xx <= top_edge.x1; ++xx) { - if ((top_edge.y0 - 1) < 0) { + for (xx = top_edge.p0.x; xx <= top_edge.p1.x; ++xx) { + if ((top_edge.p0.y - 1) < 0) { neighbour_stat->top_boundary++; } else { - if (g_area_container[xx][top_edge.y0 - 1].is_occupied) + if (pvt->tcm_map[xx][top_edge.p0.y - 1].is_occupied) neighbour_stat->top_occupied++; } /* Realized that we need to pass through the same iters for bottom edge. So trying to reduce passes by manipulating the checks */ - if ((bottom_edge.y0 + 1) > (MAX_Y_DIMMENSION - 1)) { + if ((bottom_edge.p0.y + 1) > (pvt->height - 1)) { neighbour_stat->bottom_boundary++; } else { - if (g_area_container[xx][bottom_edge.y0+1].is_occupied) + if (pvt->tcm_map[xx][bottom_edge.p0.y+1].is_occupied) neighbour_stat->bottom_occupied++; } } /* Parsing throught left and right edge */ - for (yy = left_edge.y0; yy <= left_edge.y1; ++yy) { - if ((left_edge.x0 - 1) < 0) { + for (yy = left_edge.p0.y; yy <= left_edge.p1.y; ++yy) { + if ((left_edge.p0.x - 1) < 0) { neighbour_stat->left_boundary++; } else { - if (g_area_container[left_edge.x0 - 1][yy].is_occupied) + if (pvt->tcm_map[left_edge.p0.x - 1][yy].is_occupied) neighbour_stat->left_occupied++; } - if ((right_edge.x0 + 1) > (MAX_X_DIMMENSION - 1)) { + if ((right_edge.p0.x + 1) > (pvt->width - 1)) { neighbour_stat->right_boundary++; } else { - if (g_area_container[right_edge.x0 + 1][yy].is_occupied) + if (pvt->tcm_map[right_edge.p0.x + 1][yy].is_occupied) neighbour_stat->right_occupied++; } } + + return TilerErrorNone; +} + +/** + @description: Retrieves the parent area of the page at p0.x, p0.y if + occupied + @input:co-ordinates of the page (p0.x, p0.y) whoes parent area + is required + @return 0 on success, non-0 error value on failure. On success + + parent_area will contain co-ordinates (TL & BR corner) of the parent + area +*/ +static s32 sita_get_parent(struct tcm *tcm, struct tcm_pt *pt, + struct tcm_area *parent_area) +{ + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; + if (parent_area == NULL) { + PE("NULL input found\n"); + return TilerErrorInvalidArg; + } + + if (pt->x < 0 || pt->x >= pvt->width || pt->y < 0 || + pt->y >= pvt->height) { + PE("Invalid dimensions\n"); + return TilerErrorInvalidDimension; + } + + MUTEX_LOCK(&(pvt->mtx)); + assign(parent_area, 0, 0, 0, 0); + + if (pvt->tcm_map[pt->x][pt->y].is_occupied) { + parent_area->p0.x = pvt->tcm_map[pt->x][pt->y].parent_area.p0.x; + parent_area->p0.y = pvt->tcm_map[pt->x][pt->y].parent_area.p0.y; + parent_area->p1.x = pvt->tcm_map[pt->x][pt->y].parent_area.p1.x; + parent_area->p1.y = pvt->tcm_map[pt->x][pt->y].parent_area.p1.y; + } + MUTEX_REL(&(pvt->mtx)); + return TilerErrorNone; } +static s32 move_left(struct tcm *tcm, u16 x, u16 y, u32 num_of_pages, + u16 *xx, u16 *yy) +{ + /* Num of Pages remaining to the left of the same ROW. */ + u16 num_of_pages_left = x; + u16 remain_pages = 0; + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; + + /* I want this function to be really fast and dont take too much time, + so i will not do detailed checks */ + if (x > pvt->width || y > pvt->height || xx == NULL || + yy == NULL) { + PE("Error in input arguments\n"); + return TilerErrorInvalidArg; + } + + /*Checking if we are going to go out of bound with the given + num_of_pages */ + if (num_of_pages > x + (y * pvt->width)) { + PE("Overflows off the top left corner, can go at the Max (%d) \ + to left from (%d, %d)\n", (x + y * pvt->width), x, y); + return TilerErrorOverFlow; + } + + if (num_of_pages > num_of_pages_left) { + /* we fit the num of Pages Left on the same column */ + remain_pages = num_of_pages - num_of_pages_left; + + if (0 == remain_pages % pvt->width) { + *xx = 0; + *yy = y - remain_pages / pvt->width; + } else { + *xx = pvt->width - remain_pages % + pvt->width; + *yy = y - (1 + remain_pages / pvt->width); + } + } else { + *xx = x - num_of_pages; + *yy = y; + } + return TilerErrorNone; +} + + +s32 move_right(struct tcm *tcm, u16 x, u16 y, u32 num_of_pages, + u16 *xx, u16 *yy) +{ + struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt; + u32 avail_pages = (pvt->width - x - 1) + + (pvt->height - y - 1) * pvt->width; + /* Num of Pages remaining to the Right of the same ROW. */ + u16 num_of_pages_right = pvt->width - 1 - x; + u16 remain_pages = 0; + + if (x > pvt->width || y > pvt->height || xx == NULL || + yy == NULL) { + PE("Error in input arguments"); + return TilerErrorInvalidArg; + } + + /*Checking if we are going to go out of bound with the given + num_of_pages */ + if (num_of_pages > avail_pages) { + PE("Overflows off the top Right corner, can go at the Max (%d)\ + to Right from (%d, %d)\n", avail_pages, x, y); + return TilerErrorOverFlow; + } + + if (num_of_pages > num_of_pages_right) { + remain_pages = num_of_pages - num_of_pages_right; + + if (0 == remain_pages % pvt->width) { + *xx = pvt->width - 1; + *yy = y + remain_pages / pvt->width; + } else { + *xx = remain_pages % pvt->width - 1; + *yy = y + (1 + remain_pages / pvt->width); + } + } else { + *xx = x + num_of_pages; + *yy = y; + } + + return TilerErrorNone; +} + + +#ifdef TILER_TEST_FUNCTIONS /* Test insert * Dummy insertion, No Error Checking. */ -s32 test_insert(IN struct area_spec_list *new_area) +s32 test_insert(struct tam *tcm, IN struct area_spec_list *new_area) { struct tiler_page tile; - struct area_spec area = new_area->area; + struct tcm_area area = new_area->area; if (new_area == NULL) return TilerErrorInvalidArg; tile.is_occupied = OCCUPIED; tile.reserved = 0; - tile.parent_area.x0 = area.x0; - tile.parent_area.y0 = area.y0; - tile.parent_area.x1 = area.x1; - tile.parent_area.y1 = area.y1; + tile.parent_area.p0.x = area.p0.x; + tile.parent_area.p0.y = area.p0.y; + tile.parent_area.p1.x = area.p1.x; + tile.parent_area.p1.y = area.p1.y; tile.type = new_area->area_type; - if (new_area->area_type == TWO_D) - return insert_area_with_tiler_page(&area, tile); + if (new_area->area_type == TCM_2D) + return insert_area_with_tiler_page(tcm, &area, tile); - return insert_pages_with_tiler_page(&area, tile); + return insert_pages_with_tiler_page(tcm, &area, tile); } -s32 test_dump_alloc_list() +s32 test_dump_alloc_list(struct tam *tcm) { - dump_list_entries(g_allocation_list); + dump_list_entries(pvt->res_list); return TilerErrorNone; } - -s32 test_allocate_2D_area(IN u16 w, IN u16 h, IN enum alignment align, - u16 corner, OUT struct area_spec *allocated_area) +s32 test_allocate_2D_area(struct tam *tcm, IN u16 w, IN u16 h, + u16 align, u16 corner, OUT struct tcm_area *allocated_area) { - struct area_spec scan_area = {0, 0, 0, 0}; + struct tcm_area scan_area = {0, 0, 0, 0}; s32 ret = TilerErrorNone; u16 stride = ALIGN_STRIDE(align); struct tiler_page tile; /*check if width and height are within limits */ - if (w > MAX_X_DIMMENSION || w == 0 || h > MAX_Y_DIMMENSION || h == 0) { + if (w > pvt->width || w == 0 || h > pvt->height || h == 0) { PE("Invalid dimension:: %d x %d\n", w, h); return TilerErrorInvalidDimension; } @@ -1672,99 +1918,70 @@ s32 test_allocate_2D_area(IN u16 w, IN u16 h, IN enum alignment align, } if (corner == TL_CORNER) { - assign(&scan_area, 0, 0, (MAX_X_DIMMENSION - 1), - (MAX_Y_DIMMENSION - 1)); - ret = scan_l2r_t2b(w, h, stride, &scan_area, allocated_area); + assign(&scan_area, 0, 0, (pvt->width - 1), + (pvt->height - 1)); + ret = scan_l2r_t2b(tcm, w, h, stride, &scan_area, + allocated_area); } else if (corner == TR_CORNER) { - assign(&scan_area, (MAX_X_DIMMENSION-1), 0, 0, - (MAX_Y_DIMMENSION - 1)); - ret = scan_r2l_t2b(w, h, stride, &scan_area, allocated_area); + assign(&scan_area, (pvt->width-1), 0, 0, + (pvt->height - 1)); + ret = scan_r2l_t2b(tcm, w, h, stride, &scan_area, + allocated_area); } else if (corner == BL_CORNER) { - assign(&scan_area, 0, (MAX_Y_DIMMENSION - 1), - (MAX_X_DIMMENSION - 1), 0); - ret = scan_l2r_b2t(w, h, stride, &scan_area, allocated_area); + assign(&scan_area, 0, (pvt->height - 1), + (pvt->width - 1), 0); + ret = scan_l2r_b2t(tcm, w, h, stride, &scan_area, + allocated_area); } else { - assign(&scan_area, (MAX_X_DIMMENSION - 1), - (MAX_Y_DIMMENSION - 1), 0, 0); - ret = scan_r2l_b2t(w, h, stride, &scan_area, allocated_area); + assign(&scan_area, (pvt->width - 1), + (pvt->height - 1), 0, 0); + ret = scan_r2l_b2t(tcm, w, h, stride, &scan_area, + allocated_area); } - MUTEX_LOCK(&g_mutex); + MUTEX_LOCK(&(pvt->mtx)); if (ret != TilerErrorNone) { PE("Did not find anything in the given area\n"); } else { P2("Yahoo found a fit: %s\n", AREA_STR(a_str, allocated_area)); tile.is_occupied = OCCUPIED; - assign(&tile.parent_area, allocated_area->x0, - allocated_area->y0, allocated_area->x1, allocated_area->y1); + assign(&tile.parent_area, allocated_area->p0.x, + allocated_area->p0.y, allocated_area->p1.x, + allocated_area->p1.y); /* some id, not useful now */ - tile.reserved = g_id++; + tile.reserved = pvt->id++; /* Saying that type is 2D */ - tile.type = TWO_D; + tile.type = TCM_2D; /* inserting into tiler container */ - insert_area_with_tiler_page(allocated_area, tile); + insert_area_with_tiler_page(tcm, allocated_area, tile); /*updating the list of allocations */ - insert_element(&g_allocation_list, allocated_area, TWO_D); + insert_element(&pvt->res_list, allocated_area, TCM_2D); } - MUTEX_REL(&g_mutex); + MUTEX_REL(&(pvt->mtx)); return ret; } -s32 test_get_busy_neigh_stats(u16 width, u16 height, - struct area_spec *top_left_corner, - struct neighbour_stats *neighbour_stat) +s32 test_get_busy_neigh_stats(struct tam *tcm, u16 width, u16 height, + struct tcm_area *top_left_corner, + struct neighbour_stats *neighbour_stat) { - return get_busy_neigh_stats(width, height, top_left_corner, - neighbour_stat); + return get_busy_neigh_stats(tcm, width, height, top_left_corner, + neighbour_stat); } -s32 test_check_busy(IN u16 x, u16 y) +s32 test_check_busy(struct tam *tcm, IN u16 x, u16 y) { - return (s32)g_area_container[x][y].is_occupied; + return (s32)pvt->tcm_map[x][y].is_occupied; } -/** - @description: Retrieves the parent area of the page at x0, y0 if - occupied - @input:co-ordinates of the page (x0, y0) whoes parent area is required - @return 0 on success, non-0 error value on failure. On success - - parent_area will contain co-ordinates (TL & BR corner) of the parent - area -*/ -s32 retrieve_parent_area(u16 x0, u16 y0, struct area_spec *parent_area) -{ - if (parent_area == NULL) { - PE("NULL input found\n"); - return TilerErrorInvalidArg; - } - - if (x0 < 0 || x0 >= MAX_X_DIMMENSION || y0 < 0 || - y0 >= MAX_Y_DIMMENSION){ - PE("Invalid dimensions\n"); - return TilerErrorInvalidDimension; - } - - MUTEX_LOCK(&g_mutex); - - assign(parent_area, 0, 0, 0, 0); - - if (g_area_container[x0][y0].is_occupied) { - parent_area->x0 = g_area_container[x0][y0].parent_area.x0; - parent_area->y0 = g_area_container[x0][y0].parent_area.y0; - parent_area->x1 = g_area_container[x0][y0].parent_area.x1; - parent_area->y1 = g_area_container[x0][y0].parent_area.y1; - } +#endif - MUTEX_REL(&g_mutex); - return TilerErrorNone; -} diff --git a/drivers/media/video/tiler/tcm/tcm.h b/drivers/media/video/tiler/tcm/tcm.h index c01799722fa2..ef3da6a2dd31 100644 --- a/drivers/media/video/tiler/tcm/tcm.h +++ b/drivers/media/video/tiler/tcm/tcm.h @@ -1,103 +1,313 @@ /* * tcm.h * - * Author: Ravi Ramachandra + * Created on: Mar 1, 2010 + * Authors: Ravikiran Ramachandra, Lajos Molnar * - * Tiler Container manager functions for TI OMAP processors. + * Revision History: + * 01/3/10: Defined basic structs,func ptr based 'struct tcm' + * Defined basic APIs - Ravi + * 17/3/10: Modified APIs with error checking, added additional + * field struct tmc * to tcm_area. + * Added 'tcm_slice' to retrieve topmost 2D slice + * Added 'tcm_area_is_valid' functionality - Lajos * - * Copyright (C) 2009-2010 Texas Instruments, Inc. - * - * This package is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef _TCM_H_ #define _TCM_H_ -#include "tcm_pri.h" -#include "tcm_utils.h" - -#define OCCUPIED YES -#define NOT_OCCUPIED NO +#include +#include -#define FIT YES -#define NO_FIT NO +#define TCM_1D 1 /* old:0 */ +#define TCM_2D 2 /* old:1 */ +#define ALIGN_NONE 0x0 +#define ALIGN_32 0x1 +#define ALIGN_64 0x2 +#define ALIGN_16 0x3 -/*Provide inclusive length between co-ordinates */ -#define INCL_LEN(high, low) (high - low + 1) -#define INCL_LEN_MOD(start, end) ((start > end) ? (start-end + 1) : \ -(end - start + 1)) +struct tcm; -#define TOTAL_BOUNDARY(stat) ((stat)->top_boundary + (stat)->bottom_boundary + \ - (stat)->left_boundary + (stat)->right_boundary) -#define TOTAL_OCCUPIED(stat) ((stat)->top_occupied + (stat)->bottom_occupied + \ - (stat)->left_occupied + (stat)->right_occupied) +struct tcm_pt { + u16 x; + u16 y; +}; +struct tcm_area { + int type; /* TCM_1D or 2D */ + struct tcm *tcm; /* parent */ + struct tcm_pt p0; + struct tcm_pt p1; +}; -#define TILER_USER_SPACE +struct tcm { + u16 width, height; /* container dimensions */ -#ifdef TILER_USER_SPACE -#define MUTEX_LOCK(m) (mutex_lock(m)) -#define MUTEX_REL(m) (mutex_unlock(m)) -#endif + /* 'pvt' structure shall contain any tcm details (attr) along with + linked list of allocated areas and mutex for mutually exclusive access + to the list. It may also contain copies of width and height to notice + any changes to the publicly available width and height fields. */ + void *pvt; -enum Criteria { - CR_MAX_NEIGHS = 0x01, - CR_FIRST_FOUND = 0x10, - CR_BIAS_HORIZONTAL = 0x20, - CR_BIAS_VERTICAL = 0x40, - CR_DIAGONAL_BALANCE = 0x80 + /* function table */ + s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u8 align, + struct tcm_area *area); + s32 (*reserve_1d)(struct tcm *tcm, u32 slots, struct tcm_area *area); + s32 (*free) (struct tcm *tcm, struct tcm_area *area); + s32 (*get_parent)(struct tcm *tcm, struct tcm_pt *pt, + struct tcm_area *area); + s32 (*deinit) (struct tcm *tcm); }; -struct nearness_factor { - s32 nf_x; - s32 nf_y; -}; +/*============================================================================= + BASIC TILER CONTAINER MANAGER INTERFACE +=============================================================================*/ +/** + * Template for _tcm_init method. Define as: + * TCM_INIT(_tcm_init) + * + * Allocates and initializes a tiler container manager. + * + * @param width Width of container + * @param height Height of container + * @param attr Container manager specific configuration + * arguments. Please describe these in + * your header file. + * + * @return Pointer to the allocated and initialized container + * manager. NULL on failure. DO NOT leak any memory on + * failure! + */ +#define TCM_INIT(name) \ +struct tcm *name(u16 width, u16 height, void *attr); + +/** + * Deinitialize tiler container manager. + * + * @author Ravi Ramachandra (3/1/2010) + * + * @param tcm Pointer to container manager. + * + * @return 0 on success, non-0 error value on error. The call + * should free as much memory as possible and meaningful + * even on failure. Some error codes: -ENODEV: invalid + * manager. + */ +static inline s32 tcm_deinit(struct tcm *tcm) +{ + if (tcm) + return tcm->deinit(tcm); + else + return -ENODEV; +} +/** + * Reserves a 2D area in the container. + * + * @author Ravi Ramachandra (3/1/2010) + * + * @param tcm Pointer to container manager. + * @param height Height(in pages) of area to be reserved. + * @param width Width(in pages) of area to be reserved. + * @param align Alignment requirement for top-left corner of area. Not + * all values may be supported by the container manager, + * but it must support 0 (1), 32 and 64. + * 0 value is equivalent to 1. + * @param area Pointer to where the reserved area should be stored. + * + * @return 0 on success. Non-0 error code on failure. Also, + * the tcm field of the area will be set to NULL on + * failure. Some error codes: -ENODEV: invalid manager, + * -EINVAL: invalid area, -ENOMEM: not enough space for + * allocation. + */ +static inline s32 tcm_reserve_2d(struct tcm *tcm, u16 height, u16 width, + u16 align, struct tcm_area *area) +{ + /* perform rudimentary error checking */ + s32 res = (tcm == NULL ? -ENODEV : + area == NULL ? -EINVAL : + (height > tcm->height || width > tcm->width) ? -ENOMEM : + tcm->reserve_2d(tcm, height, width, align, area)); -struct tiler_page { - u8 is_occupied; /* is tiler_page Occupied */ - /* Parent area to which this tiler_page belongs */ - struct area_spec parent_area; - u32 type; /* 1D or 2D */ - u32 reserved; -}; + if (area) + area->tcm = res ? NULL : tcm; + return res; +} -/*@descrption: init_tiler - *Initializes the tiler container +/** + * Reserves a 1D area in the container. + * + * @author Ravi Ramachandra (3/1/2010) + * + * @param tcm Pointer to container manager. + * @param slots Number of (contiguous) slots to reserve. + * @param area Pointer to where the reserved area should be stored. + * + * @return 0 on success. Non-0 error code on failure. Also, + * the tcm field of the area will be set to NULL on + * failure. Some error codes: -ENODEV: invalid manager, + * -EINVAL: invalid area, -ENOMEM: not enough space for + * allocation. */ -s32 init_tiler(void); +static inline s32 tcm_reserve_1d(struct tcm *tcm, u32 slots, + struct tcm_area *area) +{ + /* perform rudimentary error checking */ + s32 res = (tcm == NULL ? -ENODEV : + area == NULL ? -EINVAL : + slots > (tcm->width * (u32) tcm->height) ? -ENOMEM : + tcm->reserve_1d(tcm, slots, area)); -s32 deinit_tiler(void); + if (area) + area->tcm = res ? NULL : tcm; -s32 allocate_2d_area(IN u16 w, IN u16 h, IN enum alignment align, - OUT struct area_spec *allocated_area); + return res; +} + +/** + * Free a previously reserved area from the container. + * + * @author Ravi Ramachandra (3/1/2010) + * + * @param area Pointer to area reserved by a prior call to + * tcm_reserve_1d or tcm_reserve_2d call, whether + * it was successful or not. (Note: all fields of + * the structure must match.) + * + * @return 0 on success. Non-0 error code on failure. Also, the tcm + * field of the area is set to NULL on success to avoid subsequent + * freeing. This call will succeed even if supplying + * the area from a failed reserved call. + */ +static inline s32 tcm_free(struct tcm_area *area) +{ + s32 res = 0; /* free succeeds by default */ + + if (area && area->tcm) { + res = area->tcm->free(area->tcm, area); + if (res == 0) + area->tcm = NULL; + } + + return res; +} -s32 allocate_1d_pages(IN u32 num_of_pages, - OUT struct area_spec *allocated_pages); -s32 deallocate(IN struct area_spec *to_be_removed_area); +/** + * Retrieves the parent area (1D or 2D) for a given co-ordinate in the + * container. + * + * @author Ravi Ramachandra (3/1/2010) + * + * @param tcm Pointer to container manager. + * @param pt Pointer to the coordinates of a slot in the container. + * @param area Pointer to where the reserved area should be stored. + * + * @return 0 on success. Non-0 error code on failure. Also, + * the tcm field of the area will be set to NULL on + * failure. Some error codes: -ENODEV: invalid manager, + * -EINVAL: invalid area, -ENOENT: coordinate is not part of any + * active area. + */ +static inline s32 tcm_get_parent(struct tcm *tcm, struct tcm_pt *pt, + struct tcm_area *area) +{ + s32 res = (tcm == NULL ? -ENODEV : + area == NULL ? -EINVAL : + (pt->x >= tcm->width || pt->y >= tcm->height) ? -ENOENT : + tcm->get_parent(tcm, pt, area)); -s32 test_dump_alloc_list(void); + if (area) + area->tcm = res ? NULL : tcm; -s32 test_allocate_2D_area(IN u16 w, IN u16 h, IN enum alignment align, - u16 corner, OUT struct area_spec *allocated_area); + return res; +} -s32 test_get_busy_neigh_stats(u16 width, u16 height, - struct area_spec *top_left_corner, - struct neighbour_stats *neighbour_stat); +/*============================================================================= + HELPER FUNCTION FOR ANY TILER CONTAINER MANAGER +=============================================================================*/ -s32 test_check_busy_tile(IN u16 x, u16 y); +/** + * This method slices off the topmost 2D slice from the parent area, and stores + * it in the 'slice' parameter. The 'parent' parameter will get modified to + * contain the remaining portion of the area. If the whole parent area can + * fit in a 2D slice, its tcm pointer is set to NULL to mark that it is no + * longer a valid area. + * + * @author Lajos Molnar (3/17/2010) + * + * @param parent Pointer to a VALID parent area that will get modified + * @param slice Pointer to the slice area that will get modified + */ +static inline void tcm_slice(struct tcm_area *parent, struct tcm_area *slice) +{ + *slice = *parent; + + /* check if we need to slice */ + if (slice->type == TCM_1D && + slice->p0.y != slice->p1.y && + (slice->p0.x || (slice->p1.x != slice->tcm->width - 1))) { + /* set end point of slice (start always remains) */ + slice->p1.x = slice->tcm->width - 1; + slice->p1.y = (slice->p0.x) ? slice->p0.y : slice->p1.y - 1; + /* adjust remaining area */ + parent->p0.x = 0; + parent->p0.y = slice->p1.y + 1; + } else { + /* mark this as the last slice */ + parent->tcm = NULL; + } +} + +/** + * Verifies if a tcm area is logically valid. + * + * @author Lajos Molnar (3/17/2010) + * + * @param area Pointer to tcm area + * + * @return TRUE if area is logically valid, FALSE otherwise. + */ +static inline bool tcm_area_is_valid(struct tcm_area *area) +{ + return (area && area->tcm && + /* coordinate bounds */ + area->p1.x < area->tcm->width && + area->p1.y < area->tcm->height && + area->p0.y <= area->p1.y && + /* 1D coordinate relationship + p0.x check */ + ((area->type == TCM_1D && + area->p0.x < area->tcm->width && + area->p0.x + area->p0.y * area->tcm->width <= + area->p1.x + area->p1.y * area->tcm->width) || + /* 2D coordinate relationship */ + (area->type == TCM_2D && + area->p0.x <= area->p1.x)) + ); +} + +/** + * Iterate through 2D slices of a valid area. Behaves + * syntactically as a for(;;) statement. + * + * @param var Name of a local variable of type 'struct + * tcm_area *' that will get modified to + * contain each slice. + * @param area Pointer to the VALID parent area. This + * structure will not get modified + * throughout the loop. + * + */ +#define tcm_for_each_slice(var, area) \ + for (typeof(var) _parent = *area, \ + tcm_slice(_parent, &var); \ + var.tcm; tcm_slice(_parent, &var)) -s32 retrieve_parent_area(u16 x0, u16 y0, struct area_spec *parent_area); -#endif +#endif /* _TCM_H_ */ diff --git a/drivers/media/video/tiler/tcm/tcm_rr.h b/drivers/media/video/tiler/tcm/tcm_rr.h new file mode 100644 index 000000000000..20d06a139167 --- /dev/null +++ b/drivers/media/video/tiler/tcm/tcm_rr.h @@ -0,0 +1,135 @@ +/* + * tcm_rr.h + * + * Created on: Mar 25, 2010 + * Author: Ravikiran Ramachandra + * + * This header describes the private structures required + * for the implementation of (SImple Tiler Allocator) SiTA Algo. + */ + +#ifndef TCM_RR_H_ +#define TCM_RR_H_ + +#include "tcm.h" +#include "tcm_dbg.h" + +#define IN +#define OUT +#define INOUT + +#define YES 1 +#define NO 0 + +#define OCCUPIED YES +#define NOT_OCCUPIED NO + +#define FIT YES +#define NO_FIT NO + +#define TL_CORNER 0 +#define TR_CORNER 1 +#define BL_CORNER 3 +#define BR_CORNER 4 + +/*Note Alignment 64 gets the highest priority */ +#define ALIGN_STRIDE(align) ((align == ALIGN_64) ? 64 : \ + ((align == ALIGN_32) ? 32 : \ + ((align == ALIGN_16) ? 16 : 1))) + +/*Provide inclusive length between co-ordinates */ +#define INCL_LEN(high, low) (high - low + 1) +#define INCL_LEN_MOD(start, end) ((start > end) ? (start-end + 1) : \ + (end - start + 1)) + +#define TOTAL_BOUNDARY(stat) ((stat)->top_boundary + (stat)->bottom_boundary + \ + (stat)->left_boundary + (stat)->right_boundary) +#define TOTAL_OCCUPIED(stat) ((stat)->top_occupied + (stat)->bottom_occupied + \ + (stat)->left_occupied + (stat)->right_occupied) + + +#define MUTEX_LOCK(m) (mutex_lock(m)) +#define MUTEX_REL(m) (mutex_unlock(m)) + + +enum tiler_error { + TilerErrorNone = 0, + TilerErrorGeneral = -1, + TilerErrorInvalidDimension = -2, + TilerErrorNoRoom = -3, + TilerErrorInvalidArg = -4, + TilerErrorMatchNotFound = -5, + TilerErrorOverFlow = -6, + TilerErrorInvalidScanArea = -7, + TilerErrorNotSupported = -8, +}; + +enum Criteria { + CR_MAX_NEIGHS = 0x01, + CR_FIRST_FOUND = 0x10, + CR_BIAS_HORIZONTAL = 0x20, + CR_BIAS_VERTICAL = 0x40, + CR_DIAGONAL_BALANCE = 0x80 +}; + +struct nearness_factor { + s32 nf_x; + s32 nf_y; +}; + +/* + * Linked list structure + */ +struct area_spec_list; + +struct area_spec_list { + struct tcm_area area; + u16 area_type; + struct area_spec_list *next; +}; + +/* + * Everything is a rectangle with four sides and on + * each side you could have a boundary or another Tile. + * The tile could be Occupied or Not. These info is stored + */ +struct neighbour_stats { + u16 left_boundary; + u16 left_occupied; + u16 top_boundary; + u16 top_occupied; + u16 right_boundary; + u16 right_occupied; + u16 bottom_boundary; + u16 bottom_occupied; +}; + +struct tiler_page { + /* is tiler_page Occupied */ + u8 is_occupied; + /* Parent area to which this tiler_page belongs */ + struct tcm_area parent_area; + /* 1D or 2D */ + u16 type; + u32 reserved; +}; + + +struct sita_pvt { + u16 width; + u16 height; + /* This list keeps a track of all the allocations that happened in terms + of area allocated, this list is checked for removing any allocations */ + struct area_spec_list *res_list; + /* mutex */ + struct mutex mtx; + /* Divider point splitting the tiler container + horizontally and vertically */ + struct tcm_pt div_pt; + /*map of busy/non busy tiler of a given container*/ + struct tiler_page **tcm_map; + /*allocation counter, keeps rolling with */ + u32 id; +}; + +#endif /* TCM_RR_H_ */ diff --git a/drivers/media/video/tiler/tcm/tcm_sita.h b/drivers/media/video/tiler/tcm/tcm_sita.h new file mode 100644 index 000000000000..59200a348b17 --- /dev/null +++ b/drivers/media/video/tiler/tcm/tcm_sita.h @@ -0,0 +1,15 @@ +/* + * tcm_sita.h + * + * Created on: Mar 29, 2010 + * Author: Ravi Ramachandra + */ + +#ifndef TCM_SITA_H_ +#define TCM_SITA_H_ + +#include "tcm.h" + +struct tcm *sita_init(u16 width, u16 height, void *attr); + +#endif /* TCM_SITA_H_ */ diff --git a/drivers/media/video/tiler/tcm/tcm_utils.c b/drivers/media/video/tiler/tcm/tcm_utils.c index b3980d861324..d47d43156ce5 100644 --- a/drivers/media/video/tiler/tcm/tcm_utils.c +++ b/drivers/media/video/tiler/tcm/tcm_utils.c @@ -7,18 +7,19 @@ /* * Assignment Utility Function */ -void assign(IN struct area_spec *a, IN u16 x0, IN u16 y0, IN u16 x1, IN u16 y1) +void assign(IN struct tcm_area *a, IN u16 x0, IN u16 y0, IN u16 x1, IN u16 y1) { - a->x0 = x0; - a->x1 = x1; - a->y1 = y1; - a->y0 = y0; + a->p0.x = x0; + a->p0.y = y0; + a->p1.x = x1; + a->p1.y = y1; + } -void dump_area(struct area_spec *area) +void dump_area(struct tcm_area *area) { - printk(KERN_NOTICE "(%d %d) - (%d %d)\n", area->x0, area->y0, area->x1, - area->y1); + printk(KERN_NOTICE "(%d %d) - (%d %d)\n", area->p0.x, + area->p0.y, area->p1.x, area->p1.y); } @@ -26,15 +27,15 @@ void dump_area(struct area_spec *area) * Inserts a given area at the end of a given list */ s32 insert_element(INOUT struct area_spec_list **list, - IN struct area_spec *newArea, IN u16 area_type) + IN struct tcm_area *newArea, IN u16 area_type) { struct area_spec_list *list_iter = *list; struct area_spec_list *new_elem = NULL; if (list_iter == NULL) { list_iter = kmalloc(sizeof(struct area_spec_list), GFP_KERNEL); /* P("Created new List: 0x%x\n",list_iter); */ - assign(&list_iter->area, newArea->x0, newArea->y0, - newArea->x1, newArea->y1); + assign(&list_iter->area, newArea->p0.x, newArea->p0.y, + newArea->p1.x, newArea->p1.y); list_iter->area_type = area_type; list_iter->next = NULL; *list = list_iter; @@ -49,8 +50,8 @@ s32 insert_element(INOUT struct area_spec_list **list, /* P("Adding to the end of list\n"); */ /*To Do: Check for malloc failures */ new_elem = kmalloc(sizeof(struct area_spec_list), GFP_KERNEL); - assign(&new_elem->area, newArea->x0, newArea->y0, newArea->x1, - newArea->y1); + assign(&new_elem->area, newArea->p0.x, newArea->p0.y, newArea->p1.x, + newArea->p1.y); new_elem->area_type = area_type; new_elem->next = NULL; list_iter->next = new_elem; @@ -58,21 +59,21 @@ s32 insert_element(INOUT struct area_spec_list **list, } s32 rem_element_with_match(struct area_spec_list **listHead, - struct area_spec *to_be_removed, u16 *area_type) + struct tcm_area *to_be_removed, u16 *area_type) { struct area_spec_list *temp_list = NULL; struct area_spec_list *matched_elem = NULL; - struct area_spec *cur_area = NULL; + struct tcm_area *cur_area = NULL; u8 found_flag = NO; /*If the area to be removed matchs the list head itself, we need to put the next one as list head */ if (*listHead != NULL) { cur_area = &(*listHead)->area; - if (cur_area->x0 == to_be_removed->x0 && cur_area->y0 == - to_be_removed->y0 && cur_area->x1 == - to_be_removed->x1 && cur_area->y1 == - to_be_removed->y1) { + if (cur_area->p0.x == to_be_removed->p0.x && cur_area->p0.y == + to_be_removed->p0.y && cur_area->p1.x == + to_be_removed->p1.x && cur_area->p1.y == + to_be_removed->p1.y) { *area_type = (*listHead)->area_type; P1("Match found, Now Removing Area : %s\n", AREA_STR(a_str, cur_area)); @@ -90,10 +91,10 @@ s32 rem_element_with_match(struct area_spec_list **listHead, we check for the second in list */ if (temp_list->next != NULL) { cur_area = &temp_list->next->area; - if (cur_area->x0 == to_be_removed->x0 && cur_area->y0 == - to_be_removed->y0 && cur_area->x1 == - to_be_removed->x1 && cur_area->y1 == - to_be_removed->y1) { + if (cur_area->p0.x == to_be_removed->p0.x + && cur_area->p0.y == to_be_removed->p0.y + && cur_area->p1.x == to_be_removed->p1.x + && cur_area->p1.y == to_be_removed->p1.y) { P1("Match found, Now Removing Area : %s\n", AREA_STR(a_str, cur_area)); matched_elem = temp_list->next; @@ -176,86 +177,3 @@ s32 dump_neigh_stats(struct neighbour_stats *neighbour) neighbour->right_boundary); return TilerErrorNone; } - -s32 move_left(u16 x, u16 y, u32 num_of_pages, u16 *xx, u16 *yy) -{ - /* Num of Pages remaining to the left of the same ROW. */ - u16 num_of_pages_left = x; - u16 remain_pages = 0; - - /* I want this function to be really fast and dont take too much time, - so i will not do detailed checks */ - if (x > MAX_X_DIMMENSION || y > MAX_Y_DIMMENSION || xx == NULL || - yy == NULL) { - PE("Error in input arguments\n"); - return TilerErrorInvalidArg; - } - - /*Checking if we are going to go out of bound with the given - num_of_pages */ - if (num_of_pages > x + (y * MAX_X_DIMMENSION)) { - PE("Overflows off the top left corner, can go at the Max (%d)\ - to left from (%d, %d)\n", (x + y * MAX_X_DIMMENSION), - x, y); - return TilerErrorOverFlow; - } - - if (num_of_pages > num_of_pages_left) { - /* we fit the num of Pages Left on the same column */ - remain_pages = num_of_pages - num_of_pages_left; - - if (0 == remain_pages % MAX_X_DIMMENSION) { - *xx = 0; - *yy = y - remain_pages / MAX_X_DIMMENSION; - } else { - *xx = MAX_X_DIMMENSION - remain_pages % - MAX_X_DIMMENSION; - *yy = y - (1 + remain_pages / MAX_X_DIMMENSION); - } - } else { - *xx = x - num_of_pages; - *yy = y; - } - - return TilerErrorNone; -} - -s32 move_right(u16 x, u16 y, u32 num_of_pages, u16 *xx, u16 *yy) -{ - u32 avail_pages = (MAX_X_DIMMENSION - x - 1) + - (MAX_Y_DIMMENSION - y - 1) * MAX_X_DIMMENSION; - /* Num of Pages remaining to the Right of the same ROW. */ - u16 num_of_pages_right = MAX_X_DIMMENSION - 1 - x; - u16 remain_pages = 0; - - if (x > MAX_X_DIMMENSION || y > MAX_Y_DIMMENSION || xx == NULL || - yy == NULL) { - PE("Error in input arguments"); - return TilerErrorInvalidArg; - } - - /*Checking if we are going to go out of bound with the given - num_of_pages */ - if (num_of_pages > avail_pages) { - PE("Overflows off the top Right corner, can go at the Max (%d)\ - to Right from (%d, %d)\n", avail_pages, x, y); - return TilerErrorOverFlow; - } - - if (num_of_pages > num_of_pages_right) { - remain_pages = num_of_pages - num_of_pages_right; - - if (0 == remain_pages % MAX_X_DIMMENSION) { - *xx = MAX_X_DIMMENSION - 1; - *yy = y + remain_pages / MAX_X_DIMMENSION; - } else { - *xx = remain_pages % MAX_X_DIMMENSION - 1; - *yy = y + (1 + remain_pages / MAX_X_DIMMENSION); - } - } else { - *xx = x + num_of_pages; - *yy = y; - } - - return TilerErrorNone; -} diff --git a/drivers/media/video/tiler/tcm/tcm_utils.h b/drivers/media/video/tiler/tcm/tcm_utils.h index ac6a02d2cb43..294239910b29 100644 --- a/drivers/media/video/tiler/tcm/tcm_utils.h +++ b/drivers/media/video/tiler/tcm/tcm_utils.h @@ -1,29 +1,25 @@ #ifndef _TILER_UTILS_H #define _TILER_UTILS_H -#include "tcm_pri.h" +#include "tcm_rr.h" #include "tcm_dbg.h" #define AREA_STR(a_str, area) ({ \ - sprintf(a_str, "(%03d %03d)-(%03d %03d)", (area)->x0, (area)->y0, \ - (area)->x1, (area)->y1); a_str; }) + sprintf(a_str, "(%03d %03d)-(%03d %03d)", (area)->p0.x, (area)->p0.y, \ + (area)->p1.x, (area)->p1.y); a_str; }) -void assign(struct area_spec *a, u16 x0, u16 y0, u16 x1, u16 y1); -void dump_area(struct area_spec *area); +void assign(struct tcm_area *a, u16 x0, u16 y0, u16 x1, u16 y1); +void dump_area(struct tcm_area *area); s32 insert_element(INOUT struct area_spec_list **list, - IN struct area_spec *newArea, IN u16 area_type); + IN struct tcm_area *newArea, IN u16 area_type); s32 dump_list_entries(IN struct area_spec_list *list); s32 dump_neigh_stats(struct neighbour_stats *neighbour); s32 rem_element_with_match(struct area_spec_list **list, - struct area_spec *to_be_removed, u16 *area_type); + struct tcm_area *to_be_removed, u16 *area_type); s32 clean_list(struct area_spec_list **list); - -s32 move_left(u16 x, u16 y, u32 num_of_pages, u16 *xx, u16 *yy); -s32 move_right(u16 x, u16 y, u32 num_of_pages, u16 *xx, u16 *yy); - #endif -- cgit v1.2.3