# HG changeset patch # User a1ex # Date 1394617354 -7200 # Wed Mar 12 11:42:34 2014 +0200 # Branch raw-alignment # Node ID fc84146a6a40094738cff32a47dc57b413198406 # Parent e86afc9f2c41864eb59dd302713ea1cffc20345a raw_rec/mlv_rec/edmac: make sure the EDMAC line width is always multiple of 8 bytes (should fix crashes at fastest EDMAC flags, e.g. on 6D, not tested) diff -r e86afc9f2c41 -r fc84146a6a40 modules/mlv_rec/mlv_rec.c --- a/modules/mlv_rec/mlv_rec.c Mon Mar 10 12:51:05 2014 +0200 +++ b/modules/mlv_rec/mlv_rec.c Wed Mar 12 11:42:34 2014 +0200 @@ -113,8 +113,10 @@ uint32_t raw_rec_trace_ctx = TRACE_ERROR; static uint32_t abort_test = 0; /** - * resolution should be multiple of 16 horizontally - * see http://www.magiclantern.fm/forum/index.php?topic=5839.0 + * resolution (in pixels) should be multiple of 16 horizontally (see http://www.magiclantern.fm/forum/index.php?topic=5839.0) + * furthermore, resolution (in bytes) should be multiple of 8 in order to use the fastest EDMAC flags ( http://magiclantern.wikia.com/wiki/Register_Map#EDMAC ), + * which copy 16 bytes at a time, but only check for overflows every 8 bytes (can be verified experimentally) + * => if my math is not broken, this traslates to resolution being multiple of 32 pixels horizontally * use roughly 10% increments **/ @@ -524,7 +526,9 @@ int32_t left_margin = (raw_info.active_area.x1 + 7) / 8 * 8; int32_t right_margin = (raw_info.active_area.x2) / 8 * 8; int32_t max = (right_margin - left_margin) & ~15; - while (max % 16) max--; + + /* horizontal resolution *MUST* be mod 32 in order to use the fastest EDMAC flags (16 byte transfer) */ + while (max % 32) max--; max_res_x = max; /* max res Y */ diff -r e86afc9f2c41 -r fc84146a6a40 modules/raw_rec/raw_rec.c --- a/modules/raw_rec/raw_rec.c Mon Mar 10 12:51:05 2014 +0200 +++ b/modules/raw_rec/raw_rec.c Wed Mar 12 11:42:34 2014 +0200 @@ -88,8 +88,10 @@ static int cam_60d = 0; /** - * resolution should be multiple of 16 horizontally - * see http://www.magiclantern.fm/forum/index.php?topic=5839.0 + * resolution (in pixels) should be multiple of 16 horizontally (see http://www.magiclantern.fm/forum/index.php?topic=5839.0) + * furthermore, resolution (in bytes) should be multiple of 8 in order to use the fastest EDMAC flags ( http://magiclantern.wikia.com/wiki/Register_Map#EDMAC ), + * which copy 16 bytes at a time, but only check for overflows every 8 bytes (can be verified experimentally) + * => if my math is not broken, this traslates to resolution being multiple of 32 pixels horizontally * use roughly 10% increments **/ @@ -291,7 +293,9 @@ int left_margin = (raw_info.active_area.x1 + 7) / 8 * 8; int right_margin = (raw_info.active_area.x2) / 8 * 8; int max = (right_margin - left_margin) & ~15; - while (max % 16) max--; + + /* horizontal resolution *MUST* be mod 32 in order to use the fastest EDMAC flags (16 byte transfer) */ + while (max % 32) max--; max_res_x = max; /* max res Y */ diff -r e86afc9f2c41 -r fc84146a6a40 src/edmac-memcpy.c --- a/src/edmac-memcpy.c Mon Mar 10 12:51:05 2014 +0200 +++ b/src/edmac-memcpy.c Wed Mar 12 11:42:34 2014 +0200 @@ -119,6 +119,12 @@ void* edmac_copy_rectangle_cbr_start(void* dst, void* src, int src_width, int src_x, int src_y, int dst_width, int dst_x, int dst_y, int w, int h, void (*cbr_r)(void*), void (*cbr_w)(void*), void *cbr_ctx) { + /* dmaFlags are set up for 16 bytes per transfer, and overflow checking seems to be done every 8 bytes */ + /* widths that are not modulo 8 will cause overflow (the DMA will not stop) */ + /* do not remove this check, or risk permanent camera bricking */ + if (dst_width % 8) + return 0; + take_semaphore(edmac_memcpy_sem, 0); /* see wiki, register map, EDMAC what the flags mean. they are for setting up copy block size */ @@ -199,7 +207,7 @@ void* edmac_copy_rectangle_adv(void* dst, void* src, int src_width, int src_x, int src_y, int dst_width, int dst_x, int dst_y, int w, int h) { void* ans = edmac_copy_rectangle_adv_start(dst, src, src_width, src_x, src_y, dst_width, dst_x, dst_y, w, h); - edmac_copy_rectangle_adv_finish(); + if (ans) edmac_copy_rectangle_adv_finish(); return ans; }