From ae04f73ac473d0026a00d8a33829ef66187557a7 Mon Sep 17 00:00:00 2001 From: Mark Wezelenburg Date: Wed, 4 Jan 2012 00:33:46 +0100 Subject: [PATCH] [PORT FROM R2] atomisp: Acceleration API cache control BZ: 20531 The application can select the cache strategy for each individual buffer shared between atom and ISP. Change-Id: I16b27d08ff7bb3faeff93542af2887953cdfef9e Orig-Change-Id: I9e939c3cc34c9aeb50b56d0b146f265eb715cea7 Signed-off-by: Mark Wezelenburg Signed-off-by: Lokesh Gupta Reviewed-on: http://android.intel.com:8080/30363 Reviewed-by: Kruger, Jozef Tested-by: Koski, Anttu Reviewed-by: buildbot Tested-by: buildbot Reviewed-on: http://android.intel.com:8080/32448 Reviewed-by: Lampila, KalleX Tested-by: Lampila, KalleX --- drivers/media/video/atomisp/atomisp_cmd.c | 70 +++++++++++++++++++++- drivers/media/video/atomisp/atomisp_cmd.h | 3 + drivers/media/video/atomisp/atomisp_fops.c | 13 ++++ drivers/media/video/atomisp/atomisp_ioctl.c | 3 + .../video/atomisp/css/hrt/hive_isp_css_mm_hrt.h | 3 +- drivers/media/video/atomisp/css/sh_css.c | 18 +++++- drivers/media/video/atomisp/css/sh_css.h | 1 + .../media/video/atomisp/css/sh_css_accelerate.c | 6 ++ drivers/media/video/atomisp/css/sh_css_internal.h | 3 + drivers/media/video/atomisp/hmm/hmm.c | 29 +++++++-- .../media/video/atomisp/hrt/hive_isp_css_mm_hrt.c | 14 +++-- drivers/media/video/atomisp/include/hmm/hmm.h | 1 + include/linux/atomisp.h | 5 ++ 13 files changed, 153 insertions(+), 16 deletions(-) diff --git a/drivers/media/video/atomisp/atomisp_cmd.c b/drivers/media/video/atomisp/atomisp_cmd.c index 70d9ad7..77cfc7c 100644 --- a/drivers/media/video/atomisp/atomisp_cmd.c +++ b/drivers/media/video/atomisp/atomisp_cmd.c @@ -3635,10 +3635,12 @@ atomisp_acc_fw_free_args(struct atomisp_device *isp, struct sh_css_acc_fw *fw) case SH_CSS_ACC_ARG_SCALAR_IN: kfree(host->scalar.kernel_ptr); break; - case ATOMISP_ACC_ARG_FRAME: + case SH_CSS_ACC_ARG_FRAME: case SH_CSS_ACC_ARG_PTR_IN: case SH_CSS_ACC_ARG_PTR_OUT: case SH_CSS_ACC_ARG_PTR_IO: + case SH_CSS_ACC_ARG_PTR_NOFLUSH: + case SH_CSS_ACC_ARG_PTR_STABLE: hrt_isp_css_mm_free(host->ptr.hmm_ptr); break; default: @@ -3873,17 +3875,20 @@ int atomisp_acc_set_arg(struct atomisp_device *isp, ret = sh_css_set_acceleration_argument(fw, index, host->scalar.kernel_ptr, size); break; - case ATOMISP_ACC_ARG_FRAME: + case SH_CSS_ACC_ARG_FRAME: case SH_CSS_ACC_ARG_PTR_IN: case SH_CSS_ACC_ARG_PTR_OUT: case SH_CSS_ACC_ARG_PTR_IO: + case SH_CSS_ACC_ARG_PTR_NOFLUSH: + case SH_CSS_ACC_ARG_PTR_STABLE: /* Free old argument data if one already exists */ hrt_isp_css_mm_free(host->ptr.hmm_ptr); pgnr = (size + (PAGE_SIZE - 1)) >> PAGE_SHIFT; mutex_lock(&isp->isp_lock); frame_ptr = hrt_isp_css_mm_alloc_user_ptr(size, - (unsigned int)fw_arg->value, pgnr); + (unsigned int)fw_arg->value, pgnr, + type != SH_CSS_ACC_ARG_PTR_NOFLUSH); mutex_unlock(&isp->isp_lock); if (IS_ERR_OR_NULL(frame_ptr)) { @@ -3910,6 +3915,63 @@ out: return ret; } +/* Flush all flushable pointer arguments of , this function is private to this layer, yet used in atomisp_fops.c */ +void flush_acc_api_arguments(struct sh_css_acc_fw *fw) +{ + unsigned i; + + for (i = 0; i < sh_css_num_accelerator_args(fw); i++) { + enum atomisp_acc_arg_type type = sh_css_argument_type(fw, i); + union host *host; + size_t size; + switch (type) { + case SH_CSS_ACC_ARG_PTR_STABLE: + if (sh_css_acc_is_stable(fw, i)) break; + /* Fall through */ + case SH_CSS_ACC_ARG_FRAME: + case SH_CSS_ACC_ARG_PTR_IN: + case SH_CSS_ACC_ARG_PTR_OUT: + case SH_CSS_ACC_ARG_PTR_IO: + host = (union host *)sh_css_argument_get_host(fw, i); + size = sh_css_argument_get_size(fw, i); + hmm_flush(host->ptr.hmm_ptr, size); + sh_css_acc_stabilize(fw, i, true); + break; + case SH_CSS_ACC_ARG_PTR_NOFLUSH: + /* Do not flush */ + break; + default: + break; + } + + } +} + +int atomisp_acc_destabilize(struct atomisp_device *isp, + struct atomisp_acc_fw_arg *fw_arg) +{ + struct sh_css_acc_fw *fw; + unsigned int ret = 0; + unsigned int handle = fw_arg->fw_handle; + unsigned int index = fw_arg->index; + + mutex_lock(&isp->input_lock); + mutex_lock(&isp->isp_lock); + fw = atomisp_acc_get_fw(isp, handle); + if (fw == NULL) { + v4l2_err(&atomisp_dev, "%s: Invalid firmware handle\n", + __func__); + ret = -EINVAL; + } + + if (!ret) + sh_css_acc_stabilize(fw, index, false); + + mutex_unlock(&isp->isp_lock); + mutex_unlock(&isp->input_lock); + return ret; +} + int atomisp_acc_start(struct atomisp_device *isp, unsigned int *handle) { struct sh_css_acc_fw *fw; @@ -3926,6 +3988,8 @@ int atomisp_acc_start(struct atomisp_device *isp, unsigned int *handle) goto out; } + flush_acc_api_arguments(fw); + ret = sh_css_start_acceleration(fw); mutex_unlock(&isp->isp_lock); if (ret) { diff --git a/drivers/media/video/atomisp/atomisp_cmd.h b/drivers/media/video/atomisp/atomisp_cmd.h index 6587abd..6c03b6a 100644 --- a/drivers/media/video/atomisp/atomisp_cmd.h +++ b/drivers/media/video/atomisp/atomisp_cmd.h @@ -297,6 +297,9 @@ int atomisp_acc_wait(struct atomisp_device *isp, int atomisp_acc_abort(struct atomisp_device *isp, struct atomisp_acc_fw_abort *abort); +int atomisp_acc_destabilize(struct atomisp_device *isp, + struct atomisp_acc_fw_arg *fw_arg); + void atomisp_wdt_wakeup_dog(unsigned long handle); void atomisp_wdt_lock_dog(struct atomisp_device *isp); diff --git a/drivers/media/video/atomisp/atomisp_fops.c b/drivers/media/video/atomisp/atomisp_fops.c index f290b62..9bde8cc 100644 --- a/drivers/media/video/atomisp/atomisp_fops.c +++ b/drivers/media/video/atomisp/atomisp_fops.c @@ -44,6 +44,18 @@ } /* + * Implementation in atomisp_cmd.c only required to be known here as + * it is registered in CSS with "sh_css_init()" which is called from + * here. So "flush_acc_api_arguments()" is not a true public function + * + * "flush_acc_api_arguments()" needs to be accessible in CSS for the + * extension type accelerator cache control of (shared buffer pointer) + * arguments + */ +extern void flush_acc_api_arguments(struct sh_css_acc_fw *fw); + + +/* * Videobuf ops */ int atomisp_buf_setup(struct videobuf_queue *vq, @@ -321,6 +333,7 @@ static int atomisp_open(struct file *file) /* Init ISP */ if (sh_css_init(atomisp_kernel_malloc, atomisp_kernel_free, + flush_acc_api_arguments, /*NULL,*/ SH_CSS_INTERRUPT_SETTING_PULSE, isp->firmware->data, isp->firmware->size)) diff --git a/drivers/media/video/atomisp/atomisp_ioctl.c b/drivers/media/video/atomisp/atomisp_ioctl.c index 20abcd2..2359de5 100644 --- a/drivers/media/video/atomisp/atomisp_ioctl.c +++ b/drivers/media/video/atomisp/atomisp_ioctl.c @@ -1764,6 +1764,9 @@ static long atomisp_vidioc_default(struct file *file, void *fh, case ATOMISP_IOC_ACC_ABORT: return atomisp_acc_abort(isp, arg); + case ATOMISP_IOC_ACC_DESTAB: + return atomisp_acc_destabilize(isp, arg); + case ATOMISP_IOC_CAMERA_BRIDGE: /* here we convert the atomisp struct to a BC_Video struct. * We do this to avoid exporting the BC_Video struct in diff --git a/drivers/media/video/atomisp/css/hrt/hive_isp_css_mm_hrt.h b/drivers/media/video/atomisp/css/hrt/hive_isp_css_mm_hrt.h index bbe7ba1..dcd8fae 100644 --- a/drivers/media/video/atomisp/css/hrt/hive_isp_css_mm_hrt.h +++ b/drivers/media/video/atomisp/css/hrt/hive_isp_css_mm_hrt.h @@ -35,7 +35,8 @@ int hrt_isp_css_mm_set(void *virt_addr, int c, size_t bytes); /* Allocate memory, returns a virtual address */ void *hrt_isp_css_mm_alloc(size_t bytes); void *hrt_isp_css_mm_alloc_user_ptr(size_t bytes, unsigned int userptr, - unsigned int num_pages); + unsigned int num_pages, + bool cached); void *hrt_isp_css_mm_alloc_cached(size_t bytes); /* allocate memory and initialize with zeros, diff --git a/drivers/media/video/atomisp/css/sh_css.c b/drivers/media/video/atomisp/css/sh_css.c index 197a503..211b3f4 100644 --- a/drivers/media/video/atomisp/css/sh_css.c +++ b/drivers/media/video/atomisp/css/sh_css.c @@ -220,8 +220,10 @@ struct sh_css { struct sh_css_mipi_config mipi_config; bool reconfigure_css_rx; bool invalidate; + /* Register functions that are only provided by the OS */ void *(*malloc) (size_t size); void (*free) (void *ptr); + void (*flush) (struct sh_css_acc_fw *fw); enum sh_css_state state; bool two_ppc; enum sh_css_bayer_order bayer_order; @@ -280,6 +282,7 @@ struct sh_css { .invalidate = false, \ .malloc = NULL, \ .free = NULL, \ + .flush = NULL, \ .state = sh_css_state_idle, \ .two_ppc = false, \ .bayer_order = sh_css_bayer_order_grbg, \ @@ -1677,6 +1680,7 @@ enable_interrupts(void) enum sh_css_err sh_css_init(void *(*malloc_func) (size_t size), void (*free_func) (void *ptr), + void (*flush_func) (struct sh_css_acc_fw *fw), enum sh_css_interrupt_setting irq_setting, const char *fw_data, unsigned int fw_size) @@ -1684,13 +1688,17 @@ sh_css_init(void *(*malloc_func) (size_t size), static struct sh_css default_css = DEFAULT_CSS; enum sh_css_err err; - if (malloc_func == NULL || free_func == NULL) + /* "flush()" for cache control of accelrator API + * (shared buffer pointer) arguments + */ + if (malloc_func == NULL || free_func == NULL || flush_func == NULL) return sh_css_err_invalid_arguments; memcpy(&my_css, &default_css, sizeof(my_css)); my_css.malloc = malloc_func; my_css.free = free_func; + my_css.flush = flush_func; my_css.irq_edge = (irq_setting == SH_CSS_INTERRUPT_SETTING_EDGE); /* In case this has been programmed already, update internal @@ -1776,6 +1784,14 @@ sh_css_free(void *ptr) my_css.free(ptr); } +/* For Acceleration API: Flush FW (shared buffer pointer) arguments */ +void +sh_css_flush(struct sh_css_acc_fw *fw) +{ + if (fw && my_css.flush) + my_css.flush(fw); +} + void sh_css_set_print_function(int (*func) (const char *fmt, ...)) { diff --git a/drivers/media/video/atomisp/css/sh_css.h b/drivers/media/video/atomisp/css/sh_css.h index 468ea65..70f198b 100644 --- a/drivers/media/video/atomisp/css/sh_css.h +++ b/drivers/media/video/atomisp/css/sh_css.h @@ -39,6 +39,7 @@ enum sh_css_err sh_css_init(void *(*malloc_func) (size_t size), void (*free_func) (void *ptr), + void (*flush_func) (struct sh_css_acc_fw *fw), enum sh_css_interrupt_setting irq_setting, const char *fw_data, unsigned int fw_size); diff --git a/drivers/media/video/atomisp/css/sh_css_accelerate.c b/drivers/media/video/atomisp/css/sh_css_accelerate.c index 8f90cdb..831c782 100644 --- a/drivers/media/video/atomisp/css/sh_css_accelerate.c +++ b/drivers/media/video/atomisp/css/sh_css_accelerate.c @@ -259,6 +259,12 @@ sh_css_acc_start(struct sh_css_acc_fw *firmware, if (has_extension_args != is_extension) return sh_css_err_invalid_arguments; + /* NOTE: standalone accelerators have their (shared buffer pointer) + * arguments flushed in "atomisp_acc_start()" + */ + if (is_extension) + sh_css_flush(firmware); + sp_program = sh_css_sp_load_program(sp_fw, SH_CSS_ACC_PROG_NAME(firmware), (void *)firmware->header.sp_code, diff --git a/drivers/media/video/atomisp/css/sh_css_internal.h b/drivers/media/video/atomisp/css/sh_css_internal.h index 3a238af..cedbc2f 100644 --- a/drivers/media/video/atomisp/css/sh_css_internal.h +++ b/drivers/media/video/atomisp/css/sh_css_internal.h @@ -311,6 +311,9 @@ sh_css_malloc(size_t size); void sh_css_free(void *ptr); +void +sh_css_flush(struct sh_css_acc_fw *fw); + /* Check two frames for equality (format, resolution, bits per element) */ bool sh_css_frame_equal_types(const struct sh_css_frame *frame_a, diff --git a/drivers/media/video/atomisp/hmm/hmm.c b/drivers/media/video/atomisp/hmm/hmm.c index 1ceffaa..2121ef6 100644 --- a/drivers/media/video/atomisp/hmm/hmm.c +++ b/drivers/media/video/atomisp/hmm/hmm.c @@ -116,7 +116,6 @@ void *hmm_alloc(size_t bytes, enum hmm_bo_type type, v4l2_err(&atomisp_dev, "hmm_bo_bind failed.\n"); goto bind_err; } - return (void *)bo->vm_node->start; bind_err: @@ -177,7 +176,7 @@ static inline int hmm_check_bo(struct hmm_buffer_object *bo, unsigned int ptr) } /*Read function in ISP memory management*/ -int hmm_load(void *virt, void *data, unsigned int bytes) +static int load_and_flush(void *virt, void *data, unsigned int bytes) { unsigned int ptr; struct hmm_buffer_object *bo; @@ -217,13 +216,16 @@ int hmm_load(void *virt, void *data, unsigned int bytes) ptr += len; /* update ptr for next loop */ + if (des) { + #ifdef USE_SSSE3 - _ssse3_memcpy(des, src, len); + _ssse3_memcpy(des, src, len); #else - memcpy(des, src, len); + memcpy(des, src, len); #endif + des += len; + } - des += len; clflush_cache_range(src, len); kunmap(bo->pages[idx]); @@ -232,6 +234,23 @@ int hmm_load(void *virt, void *data, unsigned int bytes) return 0; } +/*Read function in ISP memory management*/ +int hmm_load(void *virt, void *data, unsigned int bytes) +{ + if (!data) { + v4l2_err(&atomisp_dev, + "hmm_load NULL argument\n"); + return -EINVAL; + } + return load_and_flush (virt, data, bytes); +} + +/*Flush hmm data from the data cache*/ +int hmm_flush(void *virt, unsigned int bytes) +{ + return load_and_flush (virt, NULL, bytes); +} + /*Write function in ISP memory management*/ int hmm_store(void *virt, const void *data, unsigned int bytes) { diff --git a/drivers/media/video/atomisp/hrt/hive_isp_css_mm_hrt.c b/drivers/media/video/atomisp/hrt/hive_isp_css_mm_hrt.c index c6583fe..ceda4e5 100644 --- a/drivers/media/video/atomisp/hrt/hive_isp_css_mm_hrt.c +++ b/drivers/media/video/atomisp/hrt/hive_isp_css_mm_hrt.c @@ -82,14 +82,15 @@ void hrt_isp_css_mm_set_user_ptr(unsigned int userptr, unsigned int num_pages) } static void *__hrt_isp_css_mm_alloc(size_t bytes, unsigned int userptr, - unsigned int num_pages) + unsigned int num_pages, + bool cached) { if (!init_done) hrt_isp_css_mm_init(); if (userptr == 0) return (void *)hmm_alloc(bytes, HMM_BO_PRIVATE, 0, 0, - HMM_UNCACHED); + cached); else { if (num_pages < ((__page_align(bytes)) >> PAGE_SHIFT)) v4l2_err(&atomisp_dev, @@ -101,19 +102,20 @@ static void *__hrt_isp_css_mm_alloc(size_t bytes, unsigned int userptr, " large than the expected size..\n"); return (void *)hmm_alloc(bytes, HMM_BO_USER, 0, - userptr, HMM_UNCACHED); + userptr, cached); } } void *hrt_isp_css_mm_alloc(size_t bytes) { - return __hrt_isp_css_mm_alloc(bytes, my_userptr, my_num_pages); + return __hrt_isp_css_mm_alloc(bytes, my_userptr, my_num_pages, false); } void *hrt_isp_css_mm_alloc_user_ptr(size_t bytes, unsigned int userptr, - unsigned int num_pages) + unsigned int num_pages, + bool cached) { - return __hrt_isp_css_mm_alloc(bytes, userptr, num_pages); + return __hrt_isp_css_mm_alloc(bytes, userptr, num_pages, cached); } void *hrt_isp_css_mm_alloc_cached(size_t bytes) diff --git a/drivers/media/video/atomisp/include/hmm/hmm.h b/drivers/media/video/atomisp/include/hmm/hmm.h index 51c29cd..cb0de07 100644 --- a/drivers/media/video/atomisp/include/hmm/hmm.h +++ b/drivers/media/video/atomisp/include/hmm/hmm.h @@ -43,6 +43,7 @@ void hmm_free(void *ptr); int hmm_load(void *virt, void *data, unsigned int bytes); int hmm_store(void *virt, const void *data, unsigned int bytes); int hmm_set(void *virt, int c, unsigned int bytes); +int hmm_flush(void *virt, unsigned int bytes); /* * get kernel memory physical address from ISP virtual address. diff --git a/include/linux/atomisp.h b/include/linux/atomisp.h index cfdb326..dbecae3 100644 --- a/include/linux/atomisp.h +++ b/include/linux/atomisp.h @@ -423,6 +423,8 @@ enum atomisp_acc_arg_type { ATOMISP_ACC_ARG_PTR_IN, /* Pointer input argument */ ATOMISP_ACC_ARG_PTR_OUT, /* Pointer output argument */ ATOMISP_ACC_ARG_PTR_IO, /* Pointer in/output argument */ + ATOMISP_ARG_PTR_NOFLUSH, /* Pointer argument will not be flushed */ + ATOMISP_ARG_PTR_STABLE, /* Pointer input argument that is stable */ ATOMISP_ACC_ARG_FRAME /* Frame argument */ }; @@ -618,6 +620,9 @@ struct v4l2_private_int_data { #define ATOMISP_IOC_S_ISP_GAMMA_CORRECTION \ _IOW('v', BASE_VIDIOC_PRIVATE + 53, struct atomisp_gc_config) +#define ATOMISP_IOC_ACC_DESTAB \ + _IOW('v', BASE_VIDIOC_PRIVATE + 54, struct atomisp_acc_fw_arg) + /* ISP Private control IDs */ #define V4L2_CID_ATOMISP_BAD_PIXEL_DETECTION \ (V4L2_CID_PRIVATE_BASE + 0) -- 2.7.4