diff options
Diffstat (limited to 'drivers/staging/media/atomisp/pci/runtime/isys')
14 files changed, 2452 insertions, 0 deletions
diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys.h b/drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys.h new file mode 100644 index 000000000000..e2aca35452c0 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys.h @@ -0,0 +1,184 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __IA_CSS_ISYS_H__ +#define __IA_CSS_ISYS_H__ + +#include <type_support.h> +#include <input_system.h> +#include <ia_css_input_port.h> +#include <ia_css_stream_format.h> +#include <ia_css_stream_public.h> +#include <system_global.h> +#include "ia_css_isys_comm.h" + +#ifdef USE_INPUT_SYSTEM_VERSION_2401 +/** + * Virtual Input System. (Input System 2401) + */ +typedef input_system_cfg_t ia_css_isys_descr_t; +/* end of Virtual Input System */ +#endif + +#if defined(USE_INPUT_SYSTEM_VERSION_2) || defined(USE_INPUT_SYSTEM_VERSION_2401) +input_system_error_t ia_css_isys_init(void); +void ia_css_isys_uninit(void); +enum mipi_port_id ia_css_isys_port_to_mipi_port( + enum mipi_port_id api_port); +#endif + +#if defined(USE_INPUT_SYSTEM_VERSION_2401) + +/** + * @brief Register one (virtual) stream. This is used to track when all + * virtual streams are configured inside the input system. The CSI RX is + * only started when all registered streams are configured. + * + * @param[in] port CSI port + * @param[in] isys_stream_id Stream handle generated with ia_css_isys_generate_stream_id() + * Must be lower than SH_CSS_MAX_ISYS_CHANNEL_NODES + * @return IA_CSS_SUCCESS if successful, IA_CSS_ERR_INTERNAL_ERROR if + * there is already a stream registered with the same handle + */ +enum ia_css_err ia_css_isys_csi_rx_register_stream( + enum mipi_port_id port, + uint32_t isys_stream_id); + +/** + * @brief Unregister one (virtual) stream. This is used to track when all + * virtual streams are configured inside the input system. The CSI RX is + * only started when all registered streams are configured. + * + * @param[in] port CSI port + * @param[in] isys_stream_id Stream handle generated with ia_css_isys_generate_stream_id() + * Must be lower than SH_CSS_MAX_ISYS_CHANNEL_NODES + * @return IA_CSS_SUCCESS if successful, IA_CSS_ERR_INTERNAL_ERROR if + * there is no stream registered with that handle + */ +enum ia_css_err ia_css_isys_csi_rx_unregister_stream( + enum mipi_port_id port, + uint32_t isys_stream_id); + +enum ia_css_err ia_css_isys_convert_compressed_format( + struct ia_css_csi2_compression *comp, + struct input_system_cfg_s *cfg); +unsigned int ia_css_csi2_calculate_input_system_alignment( + enum atomisp_input_format fmt_type); +#endif + +#if !defined(USE_INPUT_SYSTEM_VERSION_2401) +/* CSS Receiver */ +void ia_css_isys_rx_configure( + const rx_cfg_t *config, + const enum ia_css_input_mode input_mode); + +void ia_css_isys_rx_disable(void); + +void ia_css_isys_rx_enable_all_interrupts(enum mipi_port_id port); + +unsigned int ia_css_isys_rx_get_interrupt_reg(enum mipi_port_id port); +void ia_css_isys_rx_get_irq_info(enum mipi_port_id port, + unsigned int *irq_infos); +void ia_css_isys_rx_clear_irq_info(enum mipi_port_id port, + unsigned int irq_infos); +unsigned int ia_css_isys_rx_translate_irq_infos(unsigned int bits); + +#endif /* #if !defined(USE_INPUT_SYSTEM_VERSION_2401) */ + +/* @brief Translate format and compression to format type. + * + * @param[in] input_format The input format. + * @param[in] compression The compression scheme. + * @param[out] fmt_type Pointer to the resulting format type. + * @return Error code. + * + * Translate an input format and mipi compression pair to the fmt_type. + * This is normally done by the sensor, but when using the input fifo, this + * format type must be sumitted correctly by the application. + */ +enum ia_css_err ia_css_isys_convert_stream_format_to_mipi_format( + enum atomisp_input_format input_format, + mipi_predictor_t compression, + unsigned int *fmt_type); + +#ifdef USE_INPUT_SYSTEM_VERSION_2401 +/** + * Virtual Input System. (Input System 2401) + */ +ia_css_isys_error_t ia_css_isys_stream_create( + ia_css_isys_descr_t *isys_stream_descr, + ia_css_isys_stream_h isys_stream, + uint32_t isys_stream_id); + +void ia_css_isys_stream_destroy( + ia_css_isys_stream_h isys_stream); + +ia_css_isys_error_t ia_css_isys_stream_calculate_cfg( + ia_css_isys_stream_h isys_stream, + ia_css_isys_descr_t *isys_stream_descr, + ia_css_isys_stream_cfg_t *isys_stream_cfg); + +void ia_css_isys_csi_rx_lut_rmgr_init(void); + +void ia_css_isys_csi_rx_lut_rmgr_uninit(void); + +bool ia_css_isys_csi_rx_lut_rmgr_acquire( + csi_rx_backend_ID_t backend, + csi_mipi_packet_type_t packet_type, + csi_rx_backend_lut_entry_t *entry); + +void ia_css_isys_csi_rx_lut_rmgr_release( + csi_rx_backend_ID_t backend, + csi_mipi_packet_type_t packet_type, + csi_rx_backend_lut_entry_t *entry); + +void ia_css_isys_ibuf_rmgr_init(void); + +void ia_css_isys_ibuf_rmgr_uninit(void); + +bool ia_css_isys_ibuf_rmgr_acquire( + u32 size, + uint32_t *start_addr); + +void ia_css_isys_ibuf_rmgr_release( + uint32_t *start_addr); + +void ia_css_isys_dma_channel_rmgr_init(void); + +void ia_css_isys_dma_channel_rmgr_uninit(void); + +bool ia_css_isys_dma_channel_rmgr_acquire( + isys2401_dma_ID_t dma_id, + isys2401_dma_channel *channel); + +void ia_css_isys_dma_channel_rmgr_release( + isys2401_dma_ID_t dma_id, + isys2401_dma_channel *channel); + +void ia_css_isys_stream2mmio_sid_rmgr_init(void); + +void ia_css_isys_stream2mmio_sid_rmgr_uninit(void); + +bool ia_css_isys_stream2mmio_sid_rmgr_acquire( + stream2mmio_ID_t stream2mmio, + stream2mmio_sid_ID_t *sid); + +void ia_css_isys_stream2mmio_sid_rmgr_release( + stream2mmio_ID_t stream2mmio, + stream2mmio_sid_ID_t *sid); + +/* end of Virtual Input System */ +#endif + +#endif /* __IA_CSS_ISYS_H__ */ diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys_comm.h b/drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys_comm.h new file mode 100644 index 000000000000..6ad7a0cd5146 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/interface/ia_css_isys_comm.h @@ -0,0 +1,53 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __IA_CSS_ISYS_COMM_H +#define __IA_CSS_ISYS_COMM_H + +#include <type_support.h> +#include <input_system.h> + +#ifdef USE_INPUT_SYSTEM_VERSION_2401 +#include <platform_support.h> /* inline */ +#include <input_system_global.h> +#include <ia_css_stream_public.h> /* IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH */ + +#define SH_CSS_NODES_PER_THREAD 2 +#define SH_CSS_MAX_ISYS_CHANNEL_NODES (SH_CSS_MAX_SP_THREADS * SH_CSS_NODES_PER_THREAD) + +/* + * a) ia_css_isys_stream_h & ia_css_isys_stream_cfg_t come from host. + * + * b) Here it is better to use actual structures for stream handle + * instead of opaque handles. Otherwise, we need to have another + * communication channel to interpret that opaque handle(this handle is + * maintained by host and needs to be populated to sp for every stream open) + * */ +typedef virtual_input_system_stream_t *ia_css_isys_stream_h; +typedef virtual_input_system_stream_cfg_t ia_css_isys_stream_cfg_t; + +/* + * error check for ISYS APIs. + * */ +typedef bool ia_css_isys_error_t; + +static inline uint32_t ia_css_isys_generate_stream_id( + u32 sp_thread_id, + uint32_t stream_id) +{ + return sp_thread_id * IA_CSS_STREAM_MAX_ISYS_STREAM_PER_CH + stream_id; +} + +#endif /* USE_INPUT_SYSTEM_VERSION_2401*/ +#endif /*_IA_CSS_ISYS_COMM_H */ diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/csi_rx_rmgr.c b/drivers/staging/media/atomisp/pci/runtime/isys/src/csi_rx_rmgr.c new file mode 100644 index 000000000000..8f2ce2c057eb --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/csi_rx_rmgr.c @@ -0,0 +1,167 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "system_global.h" + +#ifdef USE_INPUT_SYSTEM_VERSION_2401 + +#include "assert_support.h" +#include "platform_support.h" +#include "ia_css_isys.h" +#include "bitop_support.h" +#include "ia_css_pipeline.h" /* ia_css_pipeline_get_pipe_io_status() */ +#include "sh_css_internal.h" /* sh_css_sp_pipeline_io_status + * SH_CSS_MAX_SP_THREADS + */ +#include "csi_rx_rmgr.h" + +static isys_csi_rx_rsrc_t isys_csi_rx_rsrc[N_CSI_RX_BACKEND_ID]; + +void ia_css_isys_csi_rx_lut_rmgr_init(void) +{ + memset(isys_csi_rx_rsrc, 0, sizeof(isys_csi_rx_rsrc)); +} + +void ia_css_isys_csi_rx_lut_rmgr_uninit(void) +{ + memset(isys_csi_rx_rsrc, 0, sizeof(isys_csi_rx_rsrc)); +} + +bool ia_css_isys_csi_rx_lut_rmgr_acquire( + csi_rx_backend_ID_t backend, + csi_mipi_packet_type_t packet_type, + csi_rx_backend_lut_entry_t *entry) +{ + bool retval = false; + u32 max_num_packets_of_type; + u32 num_active_of_type; + isys_csi_rx_rsrc_t *cur_rsrc = NULL; + u16 i; + + assert(backend < N_CSI_RX_BACKEND_ID); + assert((packet_type == CSI_MIPI_PACKET_TYPE_LONG) || + (packet_type == CSI_MIPI_PACKET_TYPE_SHORT)); + assert(entry); + + if ((backend < N_CSI_RX_BACKEND_ID) && (entry)) { + cur_rsrc = &isys_csi_rx_rsrc[backend]; + if (packet_type == CSI_MIPI_PACKET_TYPE_LONG) { + max_num_packets_of_type = N_LONG_PACKET_LUT_ENTRIES[backend]; + num_active_of_type = cur_rsrc->num_long_packets; + } else { + max_num_packets_of_type = N_SHORT_PACKET_LUT_ENTRIES[backend]; + num_active_of_type = cur_rsrc->num_short_packets; + } + + if (num_active_of_type < max_num_packets_of_type) { + for (i = 0; i < max_num_packets_of_type; i++) { + if (bitop_getbit(cur_rsrc->active_table, i) == 0) { + bitop_setbit(cur_rsrc->active_table, i); + + if (packet_type == CSI_MIPI_PACKET_TYPE_LONG) { + entry->long_packet_entry = i; + entry->short_packet_entry = 0; + cur_rsrc->num_long_packets++; + } else { + entry->long_packet_entry = 0; + entry->short_packet_entry = i; + cur_rsrc->num_short_packets++; + } + cur_rsrc->num_active++; + retval = true; + break; + } + } + } + } + return retval; +} + +void ia_css_isys_csi_rx_lut_rmgr_release( + csi_rx_backend_ID_t backend, + csi_mipi_packet_type_t packet_type, + csi_rx_backend_lut_entry_t *entry) +{ + u32 max_num_packets; + isys_csi_rx_rsrc_t *cur_rsrc = NULL; + u32 packet_entry = 0; + + assert(backend < N_CSI_RX_BACKEND_ID); + assert(entry); + assert((packet_type >= CSI_MIPI_PACKET_TYPE_LONG) || + (packet_type <= CSI_MIPI_PACKET_TYPE_SHORT)); + + if ((backend < N_CSI_RX_BACKEND_ID) && (entry)) { + if (packet_type == CSI_MIPI_PACKET_TYPE_LONG) { + max_num_packets = N_LONG_PACKET_LUT_ENTRIES[backend]; + packet_entry = entry->long_packet_entry; + } else { + max_num_packets = N_SHORT_PACKET_LUT_ENTRIES[backend]; + packet_entry = entry->short_packet_entry; + } + + cur_rsrc = &isys_csi_rx_rsrc[backend]; + if ((packet_entry < max_num_packets) && (cur_rsrc->num_active > 0)) { + if (bitop_getbit(cur_rsrc->active_table, packet_entry) == 1) { + bitop_clearbit(cur_rsrc->active_table, packet_entry); + + if (packet_type == CSI_MIPI_PACKET_TYPE_LONG) + cur_rsrc->num_long_packets--; + else + cur_rsrc->num_short_packets--; + cur_rsrc->num_active--; + } + } + } +} + +enum ia_css_err ia_css_isys_csi_rx_register_stream( + enum mipi_port_id port, + uint32_t isys_stream_id) +{ + enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR; + + if ((port < N_INPUT_SYSTEM_CSI_PORT) && + (isys_stream_id < SH_CSS_MAX_ISYS_CHANNEL_NODES)) { + struct sh_css_sp_pipeline_io_status *pipe_io_status; + + pipe_io_status = ia_css_pipeline_get_pipe_io_status(); + if (bitop_getbit(pipe_io_status->active[port], isys_stream_id) == 0) { + bitop_setbit(pipe_io_status->active[port], isys_stream_id); + pipe_io_status->running[port] = 0; + retval = IA_CSS_SUCCESS; + } + } + return retval; +} + +enum ia_css_err ia_css_isys_csi_rx_unregister_stream( + enum mipi_port_id port, + uint32_t isys_stream_id) +{ + enum ia_css_err retval = IA_CSS_ERR_INTERNAL_ERROR; + + if ((port < N_INPUT_SYSTEM_CSI_PORT) && + (isys_stream_id < SH_CSS_MAX_ISYS_CHANNEL_NODES)) { + struct sh_css_sp_pipeline_io_status *pipe_io_status; + + pipe_io_status = ia_css_pipeline_get_pipe_io_status(); + if (bitop_getbit(pipe_io_status->active[port], isys_stream_id) == 1) { + bitop_clearbit(pipe_io_status->active[port], isys_stream_id); + retval = IA_CSS_SUCCESS; + } + } + return retval; +} +#endif diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/csi_rx_rmgr.h b/drivers/staging/media/atomisp/pci/runtime/isys/src/csi_rx_rmgr.h new file mode 100644 index 000000000000..79d7c4b29bf4 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/csi_rx_rmgr.h @@ -0,0 +1,26 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __CSI_RX_RMGR_H_INCLUDED__ +#define __CSI_RX_RMGR_H_INCLUDED__ + +typedef struct isys_csi_rx_rsrc_s isys_csi_rx_rsrc_t; +struct isys_csi_rx_rsrc_s { + u32 active_table; + u32 num_active; + u16 num_long_packets; + u16 num_short_packets; +}; + +#endif /* __CSI_RX_RMGR_H_INCLUDED__ */ diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/ibuf_ctrl_rmgr.c b/drivers/staging/media/atomisp/pci/runtime/isys/src/ibuf_ctrl_rmgr.c new file mode 100644 index 000000000000..9055ed387673 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/ibuf_ctrl_rmgr.c @@ -0,0 +1,121 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "system_global.h" + +#include "assert_support.h" +#include "platform_support.h" +#include "ia_css_isys.h" +#include "ibuf_ctrl_rmgr.h" + +static ibuf_rsrc_t ibuf_rsrc; + +static ibuf_handle_t *getHandle(uint16_t index) +{ + ibuf_handle_t *handle = NULL; + + if (index < MAX_IBUF_HANDLES) + handle = &ibuf_rsrc.handles[index]; + return handle; +} + +void ia_css_isys_ibuf_rmgr_init(void) +{ + memset(&ibuf_rsrc, 0, sizeof(ibuf_rsrc)); + ibuf_rsrc.free_size = MAX_INPUT_BUFFER_SIZE; +} + +void ia_css_isys_ibuf_rmgr_uninit(void) +{ + memset(&ibuf_rsrc, 0, sizeof(ibuf_rsrc)); + ibuf_rsrc.free_size = MAX_INPUT_BUFFER_SIZE; +} + +bool ia_css_isys_ibuf_rmgr_acquire( + u32 size, + uint32_t *start_addr) +{ + bool retval = false; + bool input_buffer_found = false; + u32 aligned_size; + ibuf_handle_t *handle = NULL; + u16 i; + + assert(start_addr); + assert(size > 0); + + aligned_size = (size + (IBUF_ALIGN - 1)) & ~(IBUF_ALIGN - 1); + + /* Check if there is an available un-used handle with the size + * that will fulfill the request. + */ + if (ibuf_rsrc.num_active < ibuf_rsrc.num_allocated) { + for (i = 0; i < ibuf_rsrc.num_allocated; i++) { + handle = getHandle(i); + if (!handle->active) { + if (handle->size >= aligned_size) { + handle->active = true; + input_buffer_found = true; + ibuf_rsrc.num_active++; + break; + } + } + } + } + + if (!input_buffer_found) { + /* There were no available handles that fulfilled the + * request. Allocate a new handle with the requested size. + */ + if ((ibuf_rsrc.num_allocated < MAX_IBUF_HANDLES) && + (ibuf_rsrc.free_size >= aligned_size)) { + handle = getHandle(ibuf_rsrc.num_allocated); + handle->start_addr = ibuf_rsrc.free_start_addr; + handle->size = aligned_size; + handle->active = true; + + ibuf_rsrc.free_start_addr += aligned_size; + ibuf_rsrc.free_size -= aligned_size; + ibuf_rsrc.num_active++; + ibuf_rsrc.num_allocated++; + + input_buffer_found = true; + } + } + + if (input_buffer_found && handle) { + *start_addr = handle->start_addr; + retval = true; + } + + return retval; +} + +void ia_css_isys_ibuf_rmgr_release( + uint32_t *start_addr) +{ + u16 i; + ibuf_handle_t *handle = NULL; + + assert(start_addr); + + for (i = 0; i < ibuf_rsrc.num_allocated; i++) { + handle = getHandle(i); + if (handle->active && handle->start_addr == *start_addr) { + handle->active = false; + ibuf_rsrc.num_active--; + break; + } + } +} diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/ibuf_ctrl_rmgr.h b/drivers/staging/media/atomisp/pci/runtime/isys/src/ibuf_ctrl_rmgr.h new file mode 100644 index 000000000000..7155e2c6e05c --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/ibuf_ctrl_rmgr.h @@ -0,0 +1,38 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __IBUF_CTRL_RMGR_H_INCLUDED__ +#define __IBUF_CTRL_RMGR_H_INCLUDED__ + +#define MAX_IBUF_HANDLES 24 +#define MAX_INPUT_BUFFER_SIZE (64 * 1024) +#define IBUF_ALIGN 8 + +typedef struct ibuf_handle_s ibuf_handle_t; +struct ibuf_handle_s { + u32 start_addr; + u32 size; + bool active; +}; + +typedef struct ibuf_rsrc_s ibuf_rsrc_t; +struct ibuf_rsrc_s { + u32 free_start_addr; + u32 free_size; + u16 num_active; + u16 num_allocated; + ibuf_handle_t handles[MAX_IBUF_HANDLES]; +}; + +#endif /* __IBUF_CTRL_RMGR_H_INCLUDED */ diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_dma_rmgr.c b/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_dma_rmgr.c new file mode 100644 index 000000000000..930fa7a0ff53 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_dma_rmgr.c @@ -0,0 +1,87 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "system_global.h" + +#ifdef USE_INPUT_SYSTEM_VERSION_2401 + +#include "assert_support.h" +#include "platform_support.h" +#include "ia_css_isys.h" +#include "bitop_support.h" +#include "isys_dma_rmgr.h" + +static isys_dma_rsrc_t isys_dma_rsrc[N_ISYS2401_DMA_ID]; + +void ia_css_isys_dma_channel_rmgr_init(void) +{ + memset(&isys_dma_rsrc, 0, sizeof(isys_dma_rsrc_t)); +} + +void ia_css_isys_dma_channel_rmgr_uninit(void) +{ + memset(&isys_dma_rsrc, 0, sizeof(isys_dma_rsrc_t)); +} + +bool ia_css_isys_dma_channel_rmgr_acquire( + isys2401_dma_ID_t dma_id, + isys2401_dma_channel *channel) +{ + bool retval = false; + isys2401_dma_channel i; + isys2401_dma_channel max_dma_channel; + isys_dma_rsrc_t *cur_rsrc = NULL; + + assert(dma_id < N_ISYS2401_DMA_ID); + assert(channel); + + max_dma_channel = N_ISYS2401_DMA_CHANNEL_PROCS[dma_id]; + cur_rsrc = &isys_dma_rsrc[dma_id]; + + if (cur_rsrc->num_active < max_dma_channel) { + for (i = ISYS2401_DMA_CHANNEL_0; i < N_ISYS2401_DMA_CHANNEL; i++) { + if (bitop_getbit(cur_rsrc->active_table, i) == 0) { + bitop_setbit(cur_rsrc->active_table, i); + *channel = i; + cur_rsrc->num_active++; + retval = true; + break; + } + } + } + + return retval; +} + +void ia_css_isys_dma_channel_rmgr_release( + isys2401_dma_ID_t dma_id, + isys2401_dma_channel *channel) +{ + isys2401_dma_channel max_dma_channel; + isys_dma_rsrc_t *cur_rsrc = NULL; + + assert(dma_id < N_ISYS2401_DMA_ID); + assert(channel); + + max_dma_channel = N_ISYS2401_DMA_CHANNEL_PROCS[dma_id]; + cur_rsrc = &isys_dma_rsrc[dma_id]; + + if ((*channel < max_dma_channel) && (cur_rsrc->num_active > 0)) { + if (bitop_getbit(cur_rsrc->active_table, *channel) == 1) { + bitop_clearbit(cur_rsrc->active_table, *channel); + cur_rsrc->num_active--; + } + } +} +#endif diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_dma_rmgr.h b/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_dma_rmgr.h new file mode 100644 index 000000000000..e3d07ac390fc --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_dma_rmgr.h @@ -0,0 +1,24 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __ISYS_DMA_RMGR_H_INCLUDED__ +#define __ISYS_DMA_RMGR_H_INCLUDED__ + +typedef struct isys_dma_rsrc_s isys_dma_rsrc_t; +struct isys_dma_rsrc_s { + u32 active_table; + u16 num_active; +}; + +#endif /* __ISYS_DMA_RMGR_H_INCLUDED__ */ diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_init.c b/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_init.c new file mode 100644 index 000000000000..b923233ec5b0 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_init.c @@ -0,0 +1,123 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "input_system.h" + +#ifdef HAS_INPUT_SYSTEM_VERSION_2 +#include "ia_css_isys.h" +#include "platform_support.h" + +#ifdef USE_INPUT_SYSTEM_VERSION_2401 +#include "isys_dma.h" /* isys2401_dma_set_max_burst_size() */ +#include "isys_irq.h" +#endif + +#if defined(USE_INPUT_SYSTEM_VERSION_2) +input_system_error_t ia_css_isys_init(void) +{ + backend_channel_cfg_t backend_ch0; + backend_channel_cfg_t backend_ch1; + target_cfg2400_t targetB; + target_cfg2400_t targetC; + u32 acq_mem_region_size = 24; + u32 acq_nof_mem_regions = 2; + input_system_error_t error = INPUT_SYSTEM_ERR_NO_ERROR; + + memset(&backend_ch0, 0, sizeof(backend_channel_cfg_t)); + memset(&backend_ch1, 0, sizeof(backend_channel_cfg_t)); + memset(&targetB, 0, sizeof(targetB)); + memset(&targetC, 0, sizeof(targetC)); + + error = input_system_configuration_reset(); + if (error != INPUT_SYSTEM_ERR_NO_ERROR) + return error; + + error = input_system_csi_xmem_channel_cfg( + 0, /*ch_id */ + INPUT_SYSTEM_PORT_A, /*port */ + backend_ch0, /*backend_ch */ + 32, /*mem_region_size */ + 6, /*nof_mem_regions */ + acq_mem_region_size, /*acq_mem_region_size */ + acq_nof_mem_regions, /*acq_nof_mem_regions */ + targetB, /*target */ + 3); /*nof_xmem_buffers */ + if (error != INPUT_SYSTEM_ERR_NO_ERROR) + return error; + + error = input_system_csi_xmem_channel_cfg( + 1, /*ch_id */ + INPUT_SYSTEM_PORT_B, /*port */ + backend_ch0, /*backend_ch */ + 16, /*mem_region_size */ + 3, /*nof_mem_regions */ + acq_mem_region_size, /*acq_mem_region_size */ + acq_nof_mem_regions, /*acq_nof_mem_regions */ + targetB, /*target */ + 3); /*nof_xmem_buffers */ + if (error != INPUT_SYSTEM_ERR_NO_ERROR) + return error; + + error = input_system_csi_xmem_channel_cfg( + 2, /*ch_id */ + INPUT_SYSTEM_PORT_C, /*port */ + backend_ch1, /*backend_ch */ + 32, /*mem_region_size */ + 3, /*nof_mem_regions */ + acq_mem_region_size, /*acq_mem_region_size */ + acq_nof_mem_regions, /*acq_nof_mem_regions */ + targetC, /*target */ + 2); /*nof_xmem_buffers */ + if (error != INPUT_SYSTEM_ERR_NO_ERROR) + return error; + + error = input_system_configuration_commit(); + + return error; +} +#elif defined(USE_INPUT_SYSTEM_VERSION_2401) +input_system_error_t ia_css_isys_init(void) +{ + ia_css_isys_csi_rx_lut_rmgr_init(); + ia_css_isys_ibuf_rmgr_init(); + ia_css_isys_dma_channel_rmgr_init(); + ia_css_isys_stream2mmio_sid_rmgr_init(); + + isys2401_dma_set_max_burst_size(ISYS2401_DMA0_ID, + 1 /* Non Burst DMA transactions */); + + /* Enable 2401 input system IRQ status for driver to retrieve */ + isys_irqc_status_enable(ISYS_IRQ0_ID); + isys_irqc_status_enable(ISYS_IRQ1_ID); + isys_irqc_status_enable(ISYS_IRQ2_ID); + + return INPUT_SYSTEM_ERR_NO_ERROR; +} +#endif + +#if defined(USE_INPUT_SYSTEM_VERSION_2) +void ia_css_isys_uninit(void) +{ +} +#elif defined(USE_INPUT_SYSTEM_VERSION_2401) +void ia_css_isys_uninit(void) +{ + ia_css_isys_csi_rx_lut_rmgr_uninit(); + ia_css_isys_ibuf_rmgr_uninit(); + ia_css_isys_dma_channel_rmgr_uninit(); + ia_css_isys_stream2mmio_sid_rmgr_uninit(); +} +#endif + +#endif diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_stream2mmio_rmgr.c b/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_stream2mmio_rmgr.c new file mode 100644 index 000000000000..53355a55d05d --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_stream2mmio_rmgr.c @@ -0,0 +1,89 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "system_global.h" + +#ifdef USE_INPUT_SYSTEM_VERSION_2401 + +#include "assert_support.h" +#include "platform_support.h" +#include "ia_css_isys.h" +#include "bitop_support.h" +#include "isys_stream2mmio_rmgr.h" + +static isys_stream2mmio_rsrc_t isys_stream2mmio_rsrc[N_STREAM2MMIO_ID]; + +void ia_css_isys_stream2mmio_sid_rmgr_init(void) +{ + memset(isys_stream2mmio_rsrc, 0, sizeof(isys_stream2mmio_rsrc)); +} + +void ia_css_isys_stream2mmio_sid_rmgr_uninit(void) +{ + memset(isys_stream2mmio_rsrc, 0, sizeof(isys_stream2mmio_rsrc)); +} + +bool ia_css_isys_stream2mmio_sid_rmgr_acquire( + stream2mmio_ID_t stream2mmio, + stream2mmio_sid_ID_t *sid) +{ + bool retval = false; + stream2mmio_sid_ID_t max_sid; + isys_stream2mmio_rsrc_t *cur_rsrc = NULL; + stream2mmio_sid_ID_t i; + + assert(stream2mmio < N_STREAM2MMIO_ID); + assert(sid); + + if ((stream2mmio < N_STREAM2MMIO_ID) && (sid)) { + max_sid = N_STREAM2MMIO_SID_PROCS[stream2mmio]; + cur_rsrc = &isys_stream2mmio_rsrc[stream2mmio]; + + if (cur_rsrc->num_active < max_sid) { + for (i = STREAM2MMIO_SID0_ID; i < max_sid; i++) { + if (bitop_getbit(cur_rsrc->active_table, i) == 0) { + bitop_setbit(cur_rsrc->active_table, i); + *sid = i; + cur_rsrc->num_active++; + retval = true; + break; + } + } + } + } + return retval; +} + +void ia_css_isys_stream2mmio_sid_rmgr_release( + stream2mmio_ID_t stream2mmio, + stream2mmio_sid_ID_t *sid) +{ + stream2mmio_sid_ID_t max_sid; + isys_stream2mmio_rsrc_t *cur_rsrc = NULL; + + assert(stream2mmio < N_STREAM2MMIO_ID); + assert(sid); + + if ((stream2mmio < N_STREAM2MMIO_ID) && (sid)) { + max_sid = N_STREAM2MMIO_SID_PROCS[stream2mmio]; + cur_rsrc = &isys_stream2mmio_rsrc[stream2mmio]; + if ((*sid < max_sid) && (cur_rsrc->num_active > 0)) { + if (bitop_getbit(cur_rsrc->active_table, *sid) == 1) { + bitop_clearbit(cur_rsrc->active_table, *sid); + cur_rsrc->num_active--; + } + } + } +} +#endif diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_stream2mmio_rmgr.h b/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_stream2mmio_rmgr.h new file mode 100644 index 000000000000..b55cf02c8bce --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/isys_stream2mmio_rmgr.h @@ -0,0 +1,24 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __ISYS_STREAM2MMIO_RMGR_H_INCLUDED__ +#define __ISYS_STREAM2MMIO_RMGR_H_INCLUDED__ + +typedef struct isys_stream2mmio_rsrc_s isys_stream2mmio_rsrc_t; +struct isys_stream2mmio_rsrc_s { + u32 active_table; + u16 num_active; +}; + +#endif /* __ISYS_STREAM2MMIO_RMGR_H_INCLUDED__ */ diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c b/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c new file mode 100644 index 000000000000..43665ddff8ea --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c @@ -0,0 +1,600 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#define __INLINE_INPUT_SYSTEM__ +#include "input_system.h" +#include "assert_support.h" +#include "ia_css_isys.h" +#include "ia_css_irq.h" +#include "sh_css_internal.h" + +#if !defined(USE_INPUT_SYSTEM_VERSION_2401) +void ia_css_isys_rx_enable_all_interrupts(enum mipi_port_id port) +{ + hrt_data bits = receiver_port_reg_load(RX0_ID, + port, + _HRT_CSS_RECEIVER_IRQ_ENABLE_REG_IDX); + + bits |= (1U << _HRT_CSS_RECEIVER_IRQ_OVERRUN_BIT) | +#if defined(HAS_RX_VERSION_2) + (1U << _HRT_CSS_RECEIVER_IRQ_INIT_TIMEOUT_BIT) | +#endif + (1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_ENTRY_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_EXIT_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_HS_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_SYNC_HS_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_ERR_CONTROL_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_DOUBLE_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_CORRECTED_BIT) | + /*(1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_NO_CORRECTION_BIT) | */ + (1U << _HRT_CSS_RECEIVER_IRQ_ERR_CRC_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ID_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_SYNC_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_DATA_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_DATA_TIMEOUT_BIT) | + (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ESCAPE_BIT); + /*(1U << _HRT_CSS_RECEIVER_IRQ_ERR_LINE_SYNC_BIT); */ + + receiver_port_reg_store(RX0_ID, + port, + _HRT_CSS_RECEIVER_IRQ_ENABLE_REG_IDX, bits); + + /* + * The CSI is nested into the Iunit IRQ's + */ + ia_css_irq_enable(IA_CSS_IRQ_INFO_CSS_RECEIVER_ERROR, true); + + return; +} + +/* This function converts between the enum used on the CSS API and the + * internal DLI enum type. + * We do not use an array for this since we cannot use named array + * initializers in Windows. Without that there is no easy way to guarantee + * that the array values would be in the correct order. + * */ +enum mipi_port_id ia_css_isys_port_to_mipi_port(enum mipi_port_id api_port) +{ + /* In this module the validity of the inptu variable should + * have been checked already, so we do not check for erroneous + * values. */ + enum mipi_port_id port = MIPI_PORT0_ID; + + if (api_port == MIPI_PORT1_ID) + port = MIPI_PORT1_ID; + else if (api_port == MIPI_PORT2_ID) + port = MIPI_PORT2_ID; + + return port; +} + +unsigned int ia_css_isys_rx_get_interrupt_reg(enum mipi_port_id port) +{ + return receiver_port_reg_load(RX0_ID, + port, + _HRT_CSS_RECEIVER_IRQ_STATUS_REG_IDX); +} + +void ia_css_rx_get_irq_info(unsigned int *irq_infos) +{ + ia_css_rx_port_get_irq_info(MIPI_PORT1_ID, irq_infos); +} + +void ia_css_rx_port_get_irq_info(enum mipi_port_id api_port, + unsigned int *irq_infos) +{ + enum mipi_port_id port = ia_css_isys_port_to_mipi_port(api_port); + + ia_css_isys_rx_get_irq_info(port, irq_infos); +} + +void ia_css_isys_rx_get_irq_info(enum mipi_port_id port, + unsigned int *irq_infos) +{ + unsigned int bits; + + assert(irq_infos); + bits = ia_css_isys_rx_get_interrupt_reg(port); + *irq_infos = ia_css_isys_rx_translate_irq_infos(bits); +} + +/* Translate register bits to CSS API enum mask */ +unsigned int ia_css_isys_rx_translate_irq_infos(unsigned int bits) +{ + unsigned int infos = 0; + + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_OVERRUN_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_BUFFER_OVERRUN; +#if defined(HAS_RX_VERSION_2) + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_INIT_TIMEOUT_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_INIT_TIMEOUT; +#endif + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_ENTRY_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ENTER_SLEEP_MODE; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_EXIT_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_EXIT_SLEEP_MODE; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_CORRECTED_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ECC_CORRECTED; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_HS_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_SOT; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_SYNC_HS_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_SOT_SYNC; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_CONTROL_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_CONTROL; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_DOUBLE_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_CRC_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_CRC; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ID_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_SYNC_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_DATA_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_FRAME_DATA; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_DATA_TIMEOUT_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_ESCAPE_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC; + if (bits & (1U << _HRT_CSS_RECEIVER_IRQ_ERR_LINE_SYNC_BIT)) + infos |= IA_CSS_RX_IRQ_INFO_ERR_LINE_SYNC; + + return infos; +} + +void ia_css_rx_clear_irq_info(unsigned int irq_infos) +{ + ia_css_rx_port_clear_irq_info(MIPI_PORT1_ID, irq_infos); +} + +void ia_css_rx_port_clear_irq_info(enum mipi_port_id api_port, + unsigned int irq_infos) +{ + enum mipi_port_id port = ia_css_isys_port_to_mipi_port(api_port); + + ia_css_isys_rx_clear_irq_info(port, irq_infos); +} + +void ia_css_isys_rx_clear_irq_info(enum mipi_port_id port, + unsigned int irq_infos) +{ + hrt_data bits = receiver_port_reg_load(RX0_ID, + port, + _HRT_CSS_RECEIVER_IRQ_ENABLE_REG_IDX); + + /* MW: Why do we remap the receiver bitmap */ + if (irq_infos & IA_CSS_RX_IRQ_INFO_BUFFER_OVERRUN) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_OVERRUN_BIT; +#if defined(HAS_RX_VERSION_2) + if (irq_infos & IA_CSS_RX_IRQ_INFO_INIT_TIMEOUT) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_INIT_TIMEOUT_BIT; +#endif + if (irq_infos & IA_CSS_RX_IRQ_INFO_ENTER_SLEEP_MODE) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_ENTRY_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_EXIT_SLEEP_MODE) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_SLEEP_MODE_EXIT_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ECC_CORRECTED) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_CORRECTED_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_SOT) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_HS_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_SOT_SYNC) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_SOT_SYNC_HS_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_CONTROL) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_CONTROL_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_ECC_DOUBLE) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_ECC_DOUBLE_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_CRC) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_CRC_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ID) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_ID_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_FRAME_SYNC) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_SYNC_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_FRAME_DATA) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_FRAME_DATA_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_DATA_TIMEOUT) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_DATA_TIMEOUT_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_UNKNOWN_ESC) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_ESCAPE_BIT; + if (irq_infos & IA_CSS_RX_IRQ_INFO_ERR_LINE_SYNC) + bits |= 1U << _HRT_CSS_RECEIVER_IRQ_ERR_LINE_SYNC_BIT; + + receiver_port_reg_store(RX0_ID, + port, + _HRT_CSS_RECEIVER_IRQ_ENABLE_REG_IDX, bits); + + return; +} +#endif /* #if !defined(USE_INPUT_SYSTEM_VERSION_2401) */ + +enum ia_css_err ia_css_isys_convert_stream_format_to_mipi_format( + enum atomisp_input_format input_format, + mipi_predictor_t compression, + unsigned int *fmt_type) +{ + assert(fmt_type); + /* + * Custom (user defined) modes. Used for compressed + * MIPI transfers + * + * Checkpatch thinks the indent before "if" is suspect + * I think the only suspect part is the missing "else" + * because of the return. + */ + if (compression != MIPI_PREDICTOR_NONE) { + switch (input_format) { + case ATOMISP_INPUT_FORMAT_RAW_6: + *fmt_type = 6; + break; + case ATOMISP_INPUT_FORMAT_RAW_7: + *fmt_type = 7; + break; + case ATOMISP_INPUT_FORMAT_RAW_8: + *fmt_type = 8; + break; + case ATOMISP_INPUT_FORMAT_RAW_10: + *fmt_type = 10; + break; + case ATOMISP_INPUT_FORMAT_RAW_12: + *fmt_type = 12; + break; + case ATOMISP_INPUT_FORMAT_RAW_14: + *fmt_type = 14; + break; + case ATOMISP_INPUT_FORMAT_RAW_16: + *fmt_type = 16; + break; + default: + return IA_CSS_ERR_INTERNAL_ERROR; + } + return IA_CSS_SUCCESS; + } + /* + * This mapping comes from the Arasan CSS function spec + * (CSS_func_spec1.08_ahb_sep29_08.pdf). + * + * MW: For some reason the mapping is not 1-to-1 + */ + switch (input_format) { + case ATOMISP_INPUT_FORMAT_RGB_888: + *fmt_type = MIPI_FORMAT_RGB888; + break; + case ATOMISP_INPUT_FORMAT_RGB_555: + *fmt_type = MIPI_FORMAT_RGB555; + break; + case ATOMISP_INPUT_FORMAT_RGB_444: + *fmt_type = MIPI_FORMAT_RGB444; + break; + case ATOMISP_INPUT_FORMAT_RGB_565: + *fmt_type = MIPI_FORMAT_RGB565; + break; + case ATOMISP_INPUT_FORMAT_RGB_666: + *fmt_type = MIPI_FORMAT_RGB666; + break; + case ATOMISP_INPUT_FORMAT_RAW_8: + *fmt_type = MIPI_FORMAT_RAW8; + break; + case ATOMISP_INPUT_FORMAT_RAW_10: + *fmt_type = MIPI_FORMAT_RAW10; + break; + case ATOMISP_INPUT_FORMAT_RAW_6: + *fmt_type = MIPI_FORMAT_RAW6; + break; + case ATOMISP_INPUT_FORMAT_RAW_7: + *fmt_type = MIPI_FORMAT_RAW7; + break; + case ATOMISP_INPUT_FORMAT_RAW_12: + *fmt_type = MIPI_FORMAT_RAW12; + break; + case ATOMISP_INPUT_FORMAT_RAW_14: + *fmt_type = MIPI_FORMAT_RAW14; + break; + case ATOMISP_INPUT_FORMAT_YUV420_8: + *fmt_type = MIPI_FORMAT_YUV420_8; + break; + case ATOMISP_INPUT_FORMAT_YUV420_10: + *fmt_type = MIPI_FORMAT_YUV420_10; + break; + case ATOMISP_INPUT_FORMAT_YUV422_8: + *fmt_type = MIPI_FORMAT_YUV422_8; + break; + case ATOMISP_INPUT_FORMAT_YUV422_10: + *fmt_type = MIPI_FORMAT_YUV422_10; + break; + case ATOMISP_INPUT_FORMAT_YUV420_8_LEGACY: + *fmt_type = MIPI_FORMAT_YUV420_8_LEGACY; + break; + case ATOMISP_INPUT_FORMAT_EMBEDDED: + *fmt_type = MIPI_FORMAT_EMBEDDED; + break; +#ifndef USE_INPUT_SYSTEM_VERSION_2401 + case ATOMISP_INPUT_FORMAT_RAW_16: + /* This is not specified by Arasan, so we use + * 17 for now. + */ + *fmt_type = MIPI_FORMAT_RAW16; + break; + case ATOMISP_INPUT_FORMAT_BINARY_8: + *fmt_type = MIPI_FORMAT_BINARY_8; + break; +#else + case ATOMISP_INPUT_FORMAT_USER_DEF1: + *fmt_type = MIPI_FORMAT_CUSTOM0; + break; + case ATOMISP_INPUT_FORMAT_USER_DEF2: + *fmt_type = MIPI_FORMAT_CUSTOM1; + break; + case ATOMISP_INPUT_FORMAT_USER_DEF3: + *fmt_type = MIPI_FORMAT_CUSTOM2; + break; + case ATOMISP_INPUT_FORMAT_USER_DEF4: + *fmt_type = MIPI_FORMAT_CUSTOM3; + break; + case ATOMISP_INPUT_FORMAT_USER_DEF5: + *fmt_type = MIPI_FORMAT_CUSTOM4; + break; + case ATOMISP_INPUT_FORMAT_USER_DEF6: + *fmt_type = MIPI_FORMAT_CUSTOM5; + break; + case ATOMISP_INPUT_FORMAT_USER_DEF7: + *fmt_type = MIPI_FORMAT_CUSTOM6; + break; + case ATOMISP_INPUT_FORMAT_USER_DEF8: + *fmt_type = MIPI_FORMAT_CUSTOM7; + break; +#endif + + case ATOMISP_INPUT_FORMAT_YUV420_16: + case ATOMISP_INPUT_FORMAT_YUV422_16: + default: + return IA_CSS_ERR_INTERNAL_ERROR; + } + return IA_CSS_SUCCESS; +} + +#if defined(USE_INPUT_SYSTEM_VERSION_2401) +static mipi_predictor_t sh_css_csi2_compression_type_2_mipi_predictor( + enum ia_css_csi2_compression_type type) +{ + mipi_predictor_t predictor = MIPI_PREDICTOR_NONE; + + switch (type) { + case IA_CSS_CSI2_COMPRESSION_TYPE_1: + predictor = MIPI_PREDICTOR_TYPE1 - 1; + break; + case IA_CSS_CSI2_COMPRESSION_TYPE_2: + predictor = MIPI_PREDICTOR_TYPE2 - 1; + default: + break; + } + return predictor; +} + +enum ia_css_err ia_css_isys_convert_compressed_format( + struct ia_css_csi2_compression *comp, + struct input_system_cfg_s *cfg) +{ + enum ia_css_err err = IA_CSS_SUCCESS; + + assert(comp); + assert(cfg); + + if (comp->type != IA_CSS_CSI2_COMPRESSION_TYPE_NONE) { + /* compression register bit slicing + 4 bit for each user defined data type + 3 bit indicate compression scheme + 000 No compression + 001 10-6-10 + 010 10-7-10 + 011 10-8-10 + 100 12-6-12 + 101 12-6-12 + 100 12-7-12 + 110 12-8-12 + 1 bit indicate predictor + */ + if (comp->uncompressed_bits_per_pixel == UNCOMPRESSED_BITS_PER_PIXEL_10) { + switch (comp->compressed_bits_per_pixel) { + case COMPRESSED_BITS_PER_PIXEL_6: + cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_10_6_10; + break; + case COMPRESSED_BITS_PER_PIXEL_7: + cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_10_7_10; + break; + case COMPRESSED_BITS_PER_PIXEL_8: + cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_10_8_10; + break; + default: + err = IA_CSS_ERR_INVALID_ARGUMENTS; + } + } else if (comp->uncompressed_bits_per_pixel == + UNCOMPRESSED_BITS_PER_PIXEL_12) { + switch (comp->compressed_bits_per_pixel) { + case COMPRESSED_BITS_PER_PIXEL_6: + cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_12_6_12; + break; + case COMPRESSED_BITS_PER_PIXEL_7: + cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_12_7_12; + break; + case COMPRESSED_BITS_PER_PIXEL_8: + cfg->csi_port_attr.comp_scheme = MIPI_COMPRESSOR_12_8_12; + break; + default: + err = IA_CSS_ERR_INVALID_ARGUMENTS; + } + } else + err = IA_CSS_ERR_INVALID_ARGUMENTS; + cfg->csi_port_attr.comp_predictor = + sh_css_csi2_compression_type_2_mipi_predictor(comp->type); + cfg->csi_port_attr.comp_enable = true; + } else /* No compression */ + cfg->csi_port_attr.comp_enable = false; + return err; +} + +unsigned int ia_css_csi2_calculate_input_system_alignment( + enum atomisp_input_format fmt_type) +{ + unsigned int memory_alignment_in_bytes = HIVE_ISP_DDR_WORD_BYTES; + + switch (fmt_type) { + case ATOMISP_INPUT_FORMAT_RAW_6: + case ATOMISP_INPUT_FORMAT_RAW_7: + case ATOMISP_INPUT_FORMAT_RAW_8: + case ATOMISP_INPUT_FORMAT_RAW_10: + case ATOMISP_INPUT_FORMAT_RAW_12: + case ATOMISP_INPUT_FORMAT_RAW_14: + memory_alignment_in_bytes = 2 * ISP_VEC_NELEMS; + break; + case ATOMISP_INPUT_FORMAT_YUV420_8: + case ATOMISP_INPUT_FORMAT_YUV422_8: + case ATOMISP_INPUT_FORMAT_USER_DEF1: + case ATOMISP_INPUT_FORMAT_USER_DEF2: + case ATOMISP_INPUT_FORMAT_USER_DEF3: + case ATOMISP_INPUT_FORMAT_USER_DEF4: + case ATOMISP_INPUT_FORMAT_USER_DEF5: + case ATOMISP_INPUT_FORMAT_USER_DEF6: + case ATOMISP_INPUT_FORMAT_USER_DEF7: + case ATOMISP_INPUT_FORMAT_USER_DEF8: + /* Planar YUV formats need to have all planes aligned, this means + * double the alignment for the Y plane if the horizontal decimation is 2. */ + memory_alignment_in_bytes = 2 * HIVE_ISP_DDR_WORD_BYTES; + break; + case ATOMISP_INPUT_FORMAT_EMBEDDED: + default: + memory_alignment_in_bytes = HIVE_ISP_DDR_WORD_BYTES; + break; + } + return memory_alignment_in_bytes; +} + +#endif + +#if !defined(USE_INPUT_SYSTEM_VERSION_2401) +void ia_css_isys_rx_configure(const rx_cfg_t *config, + const enum ia_css_input_mode input_mode) +{ +#if defined(HAS_RX_VERSION_2) + bool port_enabled[N_MIPI_PORT_ID]; + bool any_port_enabled = false; + enum mipi_port_id port; + + if ((!config) + || (config->mode >= N_RX_MODE) + || (config->port >= N_MIPI_PORT_ID)) { + assert(0); + return; + } + for (port = (enum mipi_port_id)0; port < N_MIPI_PORT_ID; port++) { + if (is_receiver_port_enabled(RX0_ID, port)) + any_port_enabled = true; + } + /* AM: Check whether this is a problem with multiple + * streams. MS: This is the case. */ + + port = config->port; + receiver_port_enable(RX0_ID, port, false); + + port = config->port; + + /* AM: Check whether this is a problem with multiple streams. */ + if (MIPI_PORT_LANES[config->mode][port] != MIPI_0LANE_CFG) { + receiver_port_reg_store(RX0_ID, port, + _HRT_CSS_RECEIVER_FUNC_PROG_REG_IDX, + config->timeout); + receiver_port_reg_store(RX0_ID, port, + _HRT_CSS_RECEIVER_2400_INIT_COUNT_REG_IDX, + config->initcount); + receiver_port_reg_store(RX0_ID, port, + _HRT_CSS_RECEIVER_2400_SYNC_COUNT_REG_IDX, + config->synccount); + receiver_port_reg_store(RX0_ID, port, + _HRT_CSS_RECEIVER_2400_RX_COUNT_REG_IDX, + config->rxcount); + + port_enabled[port] = true; + + if (input_mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { + /* MW: A bit of a hack, straight wiring of the capture + * units,assuming they are linearly enumerated. */ + input_system_sub_system_reg_store(INPUT_SYSTEM0_ID, + GPREGS_UNIT0_ID, + HIVE_ISYS_GPREG_MULTICAST_A_IDX + + (unsigned int)port, + INPUT_SYSTEM_CSI_BACKEND); + /* MW: Like the integration test example we overwite, + * the GPREG_MUX register */ + input_system_sub_system_reg_store(INPUT_SYSTEM0_ID, + GPREGS_UNIT0_ID, + HIVE_ISYS_GPREG_MUX_IDX, + (input_system_multiplex_t)port); + } else { + /* + * AM: A bit of a hack, wiring the input system. + */ + input_system_sub_system_reg_store(INPUT_SYSTEM0_ID, + GPREGS_UNIT0_ID, + HIVE_ISYS_GPREG_MULTICAST_A_IDX + + (unsigned int)port, + INPUT_SYSTEM_INPUT_BUFFER); + input_system_sub_system_reg_store(INPUT_SYSTEM0_ID, + GPREGS_UNIT0_ID, + HIVE_ISYS_GPREG_MUX_IDX, + INPUT_SYSTEM_ACQUISITION_UNIT); + } + } + /* + * The 2ppc is shared for all ports, so we cannot + * disable->configure->enable individual ports + */ + /* AM: Check whether this is a problem with multiple streams. */ + /* MS: 2ppc should be a property per binary and should be + * enabled/disabled per binary. + * Currently it is implemented as a system wide setting due + * to effort and risks. */ + if (!any_port_enabled) { + receiver_reg_store(RX0_ID, + _HRT_CSS_RECEIVER_TWO_PIXEL_EN_REG_IDX, + config->is_two_ppc); + receiver_reg_store(RX0_ID, _HRT_CSS_RECEIVER_BE_TWO_PPC_REG_IDX, + config->is_two_ppc); + } + receiver_port_enable(RX0_ID, port, true); + /* TODO: JB: need to add the beneath used define to mizuchi */ + /* sh_css_sw_hive_isp_css_2400_system_20121224_0125\css + * \hrt\input_system_defs.h + * #define INPUT_SYSTEM_CSI_RECEIVER_SELECT_BACKENG 0X207 + */ + /* TODO: need better name for define + * input_system_reg_store(INPUT_SYSTEM0_ID, + * INPUT_SYSTEM_CSI_RECEIVER_SELECT_BACKENG, 1); + */ + input_system_reg_store(INPUT_SYSTEM0_ID, 0x207, 1); +#else +#error "rx.c: RX version must be one of {RX_VERSION_2}" +#endif + + return; +} + +void ia_css_isys_rx_disable(void) +{ + enum mipi_port_id port; + + for (port = (enum mipi_port_id)0; port < N_MIPI_PORT_ID; port++) { + receiver_port_reg_store(RX0_ID, port, + _HRT_CSS_RECEIVER_DEVICE_READY_REG_IDX, + false); + } + return; +} +#endif /* if !defined(USE_INPUT_SYSTEM_VERSION_2401) */ diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c b/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c new file mode 100644 index 000000000000..9a795a21d3e6 --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.c @@ -0,0 +1,892 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "system_global.h" + +#ifdef USE_INPUT_SYSTEM_VERSION_2401 + +#include "ia_css_isys.h" +#include "ia_css_debug.h" +#include "math_support.h" +#include "string_support.h" +#include "virtual_isys.h" +#include "isp.h" +#include "sh_css_defs.h" + +/************************************************* + * + * Forwarded Declaration + * + *************************************************/ + +static bool create_input_system_channel( + input_system_cfg_t *cfg, + bool metadata, + input_system_channel_t *channel); + +static void destroy_input_system_channel( + input_system_channel_t *channel); + +static bool create_input_system_input_port( + input_system_cfg_t *cfg, + input_system_input_port_t *input_port); + +static void destroy_input_system_input_port( + input_system_input_port_t *input_port); + +static bool calculate_input_system_channel_cfg( + input_system_channel_t *channel, + input_system_input_port_t *input_port, + input_system_cfg_t *isys_cfg, + input_system_channel_cfg_t *channel_cfg, + bool metadata); + +static bool calculate_input_system_input_port_cfg( + input_system_channel_t *channel, + input_system_input_port_t *input_port, + input_system_cfg_t *isys_cfg, + input_system_input_port_cfg_t *input_port_cfg); + +static bool acquire_sid( + stream2mmio_ID_t stream2mmio, + stream2mmio_sid_ID_t *sid); + +static void release_sid( + stream2mmio_ID_t stream2mmio, + stream2mmio_sid_ID_t *sid); + +static bool acquire_ib_buffer( + s32 bits_per_pixel, + s32 pixels_per_line, + s32 lines_per_frame, + s32 align_in_bytes, + bool online, + ib_buffer_t *buf); + +static void release_ib_buffer( + ib_buffer_t *buf); + +static bool acquire_dma_channel( + isys2401_dma_ID_t dma_id, + isys2401_dma_channel *channel); + +static void release_dma_channel( + isys2401_dma_ID_t dma_id, + isys2401_dma_channel *channel); + +static bool acquire_be_lut_entry( + csi_rx_backend_ID_t backend, + csi_mipi_packet_type_t packet_type, + csi_rx_backend_lut_entry_t *entry); + +static void release_be_lut_entry( + csi_rx_backend_ID_t backend, + csi_mipi_packet_type_t packet_type, + csi_rx_backend_lut_entry_t *entry); + +static bool calculate_tpg_cfg( + input_system_channel_t *channel, + input_system_input_port_t *input_port, + input_system_cfg_t *isys_cfg, + pixelgen_tpg_cfg_t *cfg); + +static bool calculate_prbs_cfg( + input_system_channel_t *channel, + input_system_input_port_t *input_port, + input_system_cfg_t *isys_cfg, + pixelgen_prbs_cfg_t *cfg); + +static bool calculate_fe_cfg( + const input_system_cfg_t *isys_cfg, + csi_rx_frontend_cfg_t *cfg); + +static bool calculate_be_cfg( + const input_system_input_port_t *input_port, + const input_system_cfg_t *isys_cfg, + bool metadata, + csi_rx_backend_cfg_t *cfg); + +static bool calculate_stream2mmio_cfg( + const input_system_cfg_t *isys_cfg, + bool metadata, + stream2mmio_cfg_t *cfg); + +static bool calculate_ibuf_ctrl_cfg( + const input_system_channel_t *channel, + const input_system_input_port_t *input_port, + const input_system_cfg_t *isys_cfg, + ibuf_ctrl_cfg_t *cfg); + +static bool calculate_isys2401_dma_cfg( + const input_system_channel_t *channel, + const input_system_cfg_t *isys_cfg, + isys2401_dma_cfg_t *cfg); + +static bool calculate_isys2401_dma_port_cfg( + const input_system_cfg_t *isys_cfg, + bool raw_packed, + bool metadata, + isys2401_dma_port_cfg_t *cfg); + +static csi_mipi_packet_type_t get_csi_mipi_packet_type( + int32_t data_type); + +static int32_t calculate_stride( + s32 bits_per_pixel, + s32 pixels_per_line, + bool raw_packed, + int32_t align_in_bytes); + +/* end of Forwarded Declaration */ + +/************************************************** + * + * Public Methods + * + **************************************************/ +ia_css_isys_error_t ia_css_isys_stream_create( + ia_css_isys_descr_t *isys_stream_descr, + ia_css_isys_stream_h isys_stream, + uint32_t isys_stream_id) +{ + ia_css_isys_error_t rc; + + if (!isys_stream_descr || !isys_stream || + isys_stream_id >= SH_CSS_MAX_ISYS_CHANNEL_NODES) + return false; + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "ia_css_isys_stream_create() enter:\n"); + + /*Reset isys_stream to 0*/ + memset(isys_stream, 0, sizeof(*isys_stream)); + isys_stream->enable_metadata = isys_stream_descr->metadata.enable; + isys_stream->id = isys_stream_id; + + isys_stream->linked_isys_stream_id = isys_stream_descr->linked_isys_stream_id; + rc = create_input_system_input_port(isys_stream_descr, + &isys_stream->input_port); + if (rc == false) + return false; + + rc = create_input_system_channel(isys_stream_descr, false, + &isys_stream->channel); + if (rc == false) { + destroy_input_system_input_port(&isys_stream->input_port); + return false; + } + +#ifdef ISP2401 + /* + * Early polling is required for timestamp accuracy in certain cause. + * The ISYS HW polling is started on + * ia_css_isys_stream_capture_indication() instead of + * ia_css_pipeline_sp_wait_for_isys_stream_N() as isp processing of + * capture takes longer than getting an ISYS frame + */ + isys_stream->polling_mode = isys_stream_descr->polling_mode; + +#endif + /* create metadata channel */ + if (isys_stream_descr->metadata.enable) { + rc = create_input_system_channel(isys_stream_descr, true, + &isys_stream->md_channel); + if (rc == false) { + destroy_input_system_input_port(&isys_stream->input_port); + destroy_input_system_channel(&isys_stream->channel); + return false; + } + } + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "ia_css_isys_stream_create() leave:\n"); + + return true; +} + +void ia_css_isys_stream_destroy( + ia_css_isys_stream_h isys_stream) +{ + destroy_input_system_input_port(&isys_stream->input_port); + destroy_input_system_channel(&isys_stream->channel); + if (isys_stream->enable_metadata) { + /* Destroy metadata channel only if its allocated*/ + destroy_input_system_channel(&isys_stream->md_channel); + } +} + +ia_css_isys_error_t ia_css_isys_stream_calculate_cfg( + ia_css_isys_stream_h isys_stream, + ia_css_isys_descr_t *isys_stream_descr, + ia_css_isys_stream_cfg_t *isys_stream_cfg) +{ + ia_css_isys_error_t rc; + + if (!isys_stream_cfg || + !isys_stream_descr || + !isys_stream) + return false; + + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "ia_css_isys_stream_calculate_cfg() enter:\n"); + + rc = calculate_input_system_channel_cfg( + &isys_stream->channel, + &isys_stream->input_port, + isys_stream_descr, + &isys_stream_cfg->channel_cfg, + false); + if (rc == false) + return false; + + /* configure metadata channel */ + if (isys_stream_descr->metadata.enable) { + isys_stream_cfg->enable_metadata = true; + rc = calculate_input_system_channel_cfg( + &isys_stream->md_channel, + &isys_stream->input_port, + isys_stream_descr, + &isys_stream_cfg->md_channel_cfg, + true); + if (rc == false) + return false; + } + + rc = calculate_input_system_input_port_cfg( + &isys_stream->channel, + &isys_stream->input_port, + isys_stream_descr, + &isys_stream_cfg->input_port_cfg); + if (rc == false) + return false; + + isys_stream->valid = 1; + isys_stream_cfg->valid = 1; + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, + "ia_css_isys_stream_calculate_cfg() leave:\n"); + return rc; +} + +/* end of Public Methods */ + +/************************************************** + * + * Private Methods + * + **************************************************/ +static bool create_input_system_channel( + input_system_cfg_t *cfg, + bool metadata, + input_system_channel_t *me) +{ + bool rc = true; + + me->dma_id = ISYS2401_DMA0_ID; + + switch (cfg->input_port_id) { + case INPUT_SYSTEM_CSI_PORT0_ID: + case INPUT_SYSTEM_PIXELGEN_PORT0_ID: + me->stream2mmio_id = STREAM2MMIO0_ID; + me->ibuf_ctrl_id = IBUF_CTRL0_ID; + break; + + case INPUT_SYSTEM_CSI_PORT1_ID: + case INPUT_SYSTEM_PIXELGEN_PORT1_ID: + me->stream2mmio_id = STREAM2MMIO1_ID; + me->ibuf_ctrl_id = IBUF_CTRL1_ID; + break; + + case INPUT_SYSTEM_CSI_PORT2_ID: + case INPUT_SYSTEM_PIXELGEN_PORT2_ID: + me->stream2mmio_id = STREAM2MMIO2_ID; + me->ibuf_ctrl_id = IBUF_CTRL2_ID; + break; + default: + rc = false; + break; + } + + if (!rc) + return false; + + if (!acquire_sid(me->stream2mmio_id, &me->stream2mmio_sid_id)) { + return false; + } + + if (!acquire_ib_buffer( + metadata ? cfg->metadata.bits_per_pixel : + cfg->input_port_resolution.bits_per_pixel, + metadata ? cfg->metadata.pixels_per_line : + cfg->input_port_resolution.pixels_per_line, + metadata ? cfg->metadata.lines_per_frame : + cfg->input_port_resolution.lines_per_frame, + metadata ? cfg->metadata.align_req_in_bytes : + cfg->input_port_resolution.align_req_in_bytes, + cfg->online, + &me->ib_buffer)) { + release_sid(me->stream2mmio_id, &me->stream2mmio_sid_id); + return false; + } + + if (!acquire_dma_channel(me->dma_id, &me->dma_channel)) { + release_sid(me->stream2mmio_id, &me->stream2mmio_sid_id); + release_ib_buffer(&me->ib_buffer); + return false; + } + + return true; +} + +static void destroy_input_system_channel( + input_system_channel_t *me) +{ + release_sid(me->stream2mmio_id, + &me->stream2mmio_sid_id); + + release_ib_buffer(&me->ib_buffer); + + release_dma_channel(me->dma_id, &me->dma_channel); +} + +static bool create_input_system_input_port( + input_system_cfg_t *cfg, + input_system_input_port_t *me) +{ + csi_mipi_packet_type_t packet_type; + bool rc = true; + + switch (cfg->input_port_id) { + case INPUT_SYSTEM_CSI_PORT0_ID: + me->csi_rx.frontend_id = CSI_RX_FRONTEND0_ID; + me->csi_rx.backend_id = CSI_RX_BACKEND0_ID; + + packet_type = get_csi_mipi_packet_type(cfg->csi_port_attr.fmt_type); + me->csi_rx.packet_type = packet_type; + + rc = acquire_be_lut_entry( + me->csi_rx.backend_id, + packet_type, + &me->csi_rx.backend_lut_entry); + break; + case INPUT_SYSTEM_PIXELGEN_PORT0_ID: + me->pixelgen.pixelgen_id = PIXELGEN0_ID; + break; + case INPUT_SYSTEM_CSI_PORT1_ID: + me->csi_rx.frontend_id = CSI_RX_FRONTEND1_ID; + me->csi_rx.backend_id = CSI_RX_BACKEND1_ID; + + packet_type = get_csi_mipi_packet_type(cfg->csi_port_attr.fmt_type); + me->csi_rx.packet_type = packet_type; + + rc = acquire_be_lut_entry( + me->csi_rx.backend_id, + packet_type, + &me->csi_rx.backend_lut_entry); + break; + case INPUT_SYSTEM_PIXELGEN_PORT1_ID: + me->pixelgen.pixelgen_id = PIXELGEN1_ID; + + break; + case INPUT_SYSTEM_CSI_PORT2_ID: + me->csi_rx.frontend_id = CSI_RX_FRONTEND2_ID; + me->csi_rx.backend_id = CSI_RX_BACKEND2_ID; + + packet_type = get_csi_mipi_packet_type(cfg->csi_port_attr.fmt_type); + me->csi_rx.packet_type = packet_type; + + rc = acquire_be_lut_entry( + me->csi_rx.backend_id, + packet_type, + &me->csi_rx.backend_lut_entry); + break; + case INPUT_SYSTEM_PIXELGEN_PORT2_ID: + me->pixelgen.pixelgen_id = PIXELGEN2_ID; + break; + default: + rc = false; + break; + } + + me->source_type = cfg->mode; + + /* for metadata */ + me->metadata.packet_type = CSI_MIPI_PACKET_TYPE_UNDEFINED; + if (rc && cfg->metadata.enable) { + me->metadata.packet_type = get_csi_mipi_packet_type( + cfg->metadata.fmt_type); + rc = acquire_be_lut_entry( + me->csi_rx.backend_id, + me->metadata.packet_type, + &me->metadata.backend_lut_entry); + } + + return rc; +} + +static void destroy_input_system_input_port( + input_system_input_port_t *me) +{ + if (me->source_type == INPUT_SYSTEM_SOURCE_TYPE_SENSOR) { + release_be_lut_entry( + me->csi_rx.backend_id, + me->csi_rx.packet_type, + &me->csi_rx.backend_lut_entry); + } + + if (me->metadata.packet_type != CSI_MIPI_PACKET_TYPE_UNDEFINED) { + /*Free the backend lut allocated for metadata*/ + release_be_lut_entry( + me->csi_rx.backend_id, + me->metadata.packet_type, + &me->metadata.backend_lut_entry); + } +} + +static bool calculate_input_system_channel_cfg( + input_system_channel_t *channel, + input_system_input_port_t *input_port, + input_system_cfg_t *isys_cfg, + input_system_channel_cfg_t *channel_cfg, + bool metadata) +{ + bool rc; + + rc = calculate_stream2mmio_cfg(isys_cfg, metadata, + &channel_cfg->stream2mmio_cfg); + if (!rc) + return false; + + rc = calculate_ibuf_ctrl_cfg( + channel, + input_port, + isys_cfg, + &channel_cfg->ibuf_ctrl_cfg); + if (!rc) + return false; + if (metadata) + channel_cfg->ibuf_ctrl_cfg.stores_per_frame = + isys_cfg->metadata.lines_per_frame; + + rc = calculate_isys2401_dma_cfg( + channel, + isys_cfg, + &channel_cfg->dma_cfg); + if (!rc) + return false; + + rc = calculate_isys2401_dma_port_cfg( + isys_cfg, + false, + metadata, + &channel_cfg->dma_src_port_cfg); + if (!rc) + return false; + + rc = calculate_isys2401_dma_port_cfg( + isys_cfg, + isys_cfg->raw_packed, + metadata, + &channel_cfg->dma_dest_port_cfg); + if (!rc) + return false; + + return true; +} + +static bool calculate_input_system_input_port_cfg( + input_system_channel_t *channel, + input_system_input_port_t *input_port, + input_system_cfg_t *isys_cfg, + input_system_input_port_cfg_t *input_port_cfg) +{ + bool rc; + + switch (input_port->source_type) { + case INPUT_SYSTEM_SOURCE_TYPE_SENSOR: + rc = calculate_fe_cfg( + isys_cfg, + &input_port_cfg->csi_rx_cfg.frontend_cfg); + + rc &= calculate_be_cfg( + input_port, + isys_cfg, + false, + &input_port_cfg->csi_rx_cfg.backend_cfg); + + if (rc && isys_cfg->metadata.enable) + rc &= calculate_be_cfg(input_port, isys_cfg, true, + &input_port_cfg->csi_rx_cfg.md_backend_cfg); + break; + case INPUT_SYSTEM_SOURCE_TYPE_TPG: + rc = calculate_tpg_cfg( + channel, + input_port, + isys_cfg, + &input_port_cfg->pixelgen_cfg.tpg_cfg); + break; + case INPUT_SYSTEM_SOURCE_TYPE_PRBS: + rc = calculate_prbs_cfg( + channel, + input_port, + isys_cfg, + &input_port_cfg->pixelgen_cfg.prbs_cfg); + break; + default: + rc = false; + break; + } + + return rc; +} + +static bool acquire_sid( + stream2mmio_ID_t stream2mmio, + stream2mmio_sid_ID_t *sid) +{ + return ia_css_isys_stream2mmio_sid_rmgr_acquire(stream2mmio, sid); +} + +static void release_sid( + stream2mmio_ID_t stream2mmio, + stream2mmio_sid_ID_t *sid) +{ + ia_css_isys_stream2mmio_sid_rmgr_release(stream2mmio, sid); +} + +/* See also: ia_css_dma_configure_from_info() */ +static int32_t calculate_stride( + s32 bits_per_pixel, + s32 pixels_per_line, + bool raw_packed, + int32_t align_in_bytes) +{ + s32 bytes_per_line; + s32 pixels_per_word; + s32 words_per_line; + s32 pixels_per_line_padded; + + pixels_per_line_padded = CEIL_MUL(pixels_per_line, align_in_bytes); + + if (!raw_packed) + bits_per_pixel = CEIL_MUL(bits_per_pixel, 8); + + pixels_per_word = HIVE_ISP_DDR_WORD_BITS / bits_per_pixel; + words_per_line = ceil_div(pixels_per_line_padded, pixels_per_word); + bytes_per_line = HIVE_ISP_DDR_WORD_BYTES * words_per_line; + + return bytes_per_line; +} + +static bool acquire_ib_buffer( + s32 bits_per_pixel, + s32 pixels_per_line, + s32 lines_per_frame, + s32 align_in_bytes, + bool online, + ib_buffer_t *buf) +{ + buf->stride = calculate_stride(bits_per_pixel, pixels_per_line, false, + align_in_bytes); + if (online) + buf->lines = 4; /* use double buffering for online usecases */ + else + buf->lines = 2; + + (void)(lines_per_frame); + return ia_css_isys_ibuf_rmgr_acquire(buf->stride * buf->lines, + &buf->start_addr); +} + +static void release_ib_buffer( + ib_buffer_t *buf) +{ + ia_css_isys_ibuf_rmgr_release(&buf->start_addr); +} + +static bool acquire_dma_channel( + isys2401_dma_ID_t dma_id, + isys2401_dma_channel *channel) +{ + return ia_css_isys_dma_channel_rmgr_acquire(dma_id, channel); +} + +static void release_dma_channel( + isys2401_dma_ID_t dma_id, + isys2401_dma_channel *channel) +{ + ia_css_isys_dma_channel_rmgr_release(dma_id, channel); +} + +static bool acquire_be_lut_entry( + csi_rx_backend_ID_t backend, + csi_mipi_packet_type_t packet_type, + csi_rx_backend_lut_entry_t *entry) +{ + return ia_css_isys_csi_rx_lut_rmgr_acquire(backend, packet_type, entry); +} + +static void release_be_lut_entry( + csi_rx_backend_ID_t backend, + csi_mipi_packet_type_t packet_type, + csi_rx_backend_lut_entry_t *entry) +{ + ia_css_isys_csi_rx_lut_rmgr_release(backend, packet_type, entry); +} + +static bool calculate_tpg_cfg( + input_system_channel_t *channel, + input_system_input_port_t *input_port, + input_system_cfg_t *isys_cfg, + pixelgen_tpg_cfg_t *cfg) +{ + (void)channel; + (void)input_port; + + memcpy_s( + (void *)cfg, + sizeof(pixelgen_tpg_cfg_t), + (void *)(&isys_cfg->tpg_port_attr), + sizeof(pixelgen_tpg_cfg_t)); + return true; +} + +static bool calculate_prbs_cfg( + input_system_channel_t *channel, + input_system_input_port_t *input_port, + input_system_cfg_t *isys_cfg, + pixelgen_prbs_cfg_t *cfg) +{ + (void)channel; + (void)input_port; + + memcpy_s( + (void *)cfg, + sizeof(pixelgen_prbs_cfg_t), + (void *)(&isys_cfg->prbs_port_attr), + sizeof(pixelgen_prbs_cfg_t)); + return true; +} + +static bool calculate_fe_cfg( + const input_system_cfg_t *isys_cfg, + csi_rx_frontend_cfg_t *cfg) +{ + cfg->active_lanes = isys_cfg->csi_port_attr.active_lanes; + return true; +} + +static bool calculate_be_cfg( + const input_system_input_port_t *input_port, + const input_system_cfg_t *isys_cfg, + bool metadata, + csi_rx_backend_cfg_t *cfg) +{ + memcpy_s( + (void *)(&cfg->lut_entry), + sizeof(csi_rx_backend_lut_entry_t), + metadata ? (void *)(&input_port->metadata.backend_lut_entry) : + (void *)(&input_port->csi_rx.backend_lut_entry), + sizeof(csi_rx_backend_lut_entry_t)); + + cfg->csi_mipi_cfg.virtual_channel = isys_cfg->csi_port_attr.ch_id; + if (metadata) { + cfg->csi_mipi_packet_type = get_csi_mipi_packet_type( + isys_cfg->metadata.fmt_type); + cfg->csi_mipi_cfg.comp_enable = false; + cfg->csi_mipi_cfg.data_type = isys_cfg->metadata.fmt_type; + } else { + cfg->csi_mipi_packet_type = get_csi_mipi_packet_type( + isys_cfg->csi_port_attr.fmt_type); + cfg->csi_mipi_cfg.data_type = isys_cfg->csi_port_attr.fmt_type; + cfg->csi_mipi_cfg.comp_enable = isys_cfg->csi_port_attr.comp_enable; + cfg->csi_mipi_cfg.comp_scheme = isys_cfg->csi_port_attr.comp_scheme; + cfg->csi_mipi_cfg.comp_predictor = isys_cfg->csi_port_attr.comp_predictor; + cfg->csi_mipi_cfg.comp_bit_idx = cfg->csi_mipi_cfg.data_type - + MIPI_FORMAT_CUSTOM0; + } + + return true; +} + +static bool calculate_stream2mmio_cfg( + const input_system_cfg_t *isys_cfg, + bool metadata, + stream2mmio_cfg_t *cfg +) +{ + cfg->bits_per_pixel = metadata ? isys_cfg->metadata.bits_per_pixel : + isys_cfg->input_port_resolution.bits_per_pixel; + + cfg->enable_blocking = + ((isys_cfg->mode == INPUT_SYSTEM_SOURCE_TYPE_TPG) || + (isys_cfg->mode == INPUT_SYSTEM_SOURCE_TYPE_PRBS)); + + return true; +} + +static bool calculate_ibuf_ctrl_cfg( + const input_system_channel_t *channel, + const input_system_input_port_t *input_port, + const input_system_cfg_t *isys_cfg, + ibuf_ctrl_cfg_t *cfg) +{ + const s32 bits_per_byte = 8; + s32 bits_per_pixel; + s32 bytes_per_pixel; + s32 left_padding; + + (void)input_port; + + bits_per_pixel = isys_cfg->input_port_resolution.bits_per_pixel; + bytes_per_pixel = ceil_div(bits_per_pixel, bits_per_byte); + + left_padding = CEIL_MUL(isys_cfg->output_port_attr.left_padding, ISP_VEC_NELEMS) + * bytes_per_pixel; + + cfg->online = isys_cfg->online; + + cfg->dma_cfg.channel = channel->dma_channel; + cfg->dma_cfg.cmd = _DMA_V2_MOVE_A2B_NO_SYNC_CHK_COMMAND; + + cfg->dma_cfg.shift_returned_items = 0; + cfg->dma_cfg.elems_per_word_in_ibuf = 0; + cfg->dma_cfg.elems_per_word_in_dest = 0; + + cfg->ib_buffer.start_addr = channel->ib_buffer.start_addr; + cfg->ib_buffer.stride = channel->ib_buffer.stride; + cfg->ib_buffer.lines = channel->ib_buffer.lines; + + /* + #ifndef ISP2401 + * zhengjie.lu@intel.com: + #endif + * "dest_buf_cfg" should be part of the input system output + * port configuration. + * + * TODO: move "dest_buf_cfg" to the input system output + * port configuration. + */ + + /* input_buf addr only available in sched mode; + this buffer is allocated in isp, crun mode addr + can be passed by after ISP allocation */ + if (cfg->online) { + cfg->dest_buf_cfg.start_addr = ISP_INPUT_BUF_START_ADDR + left_padding; + cfg->dest_buf_cfg.stride = bytes_per_pixel + * isys_cfg->output_port_attr.max_isp_input_width; + cfg->dest_buf_cfg.lines = LINES_OF_ISP_INPUT_BUF; + } else if (isys_cfg->raw_packed) { + cfg->dest_buf_cfg.stride = calculate_stride(bits_per_pixel, + isys_cfg->input_port_resolution.pixels_per_line, + isys_cfg->raw_packed, + isys_cfg->input_port_resolution.align_req_in_bytes); + } else { + cfg->dest_buf_cfg.stride = channel->ib_buffer.stride; + } + + /* + #ifndef ISP2401 + * zhengjie.lu@intel.com: + #endif + * "items_per_store" is hard coded as "1", which is ONLY valid + * when the CSI-MIPI long packet is transferred. + * + * TODO: After the 1st stage of MERR+, make the proper solution to + * configure "items_per_store" so that it can also handle the CSI-MIPI + * short packet. + */ + cfg->items_per_store = 1; + + cfg->stores_per_frame = isys_cfg->input_port_resolution.lines_per_frame; + + cfg->stream2mmio_cfg.sync_cmd = _STREAM2MMIO_CMD_TOKEN_SYNC_FRAME; + + /* TODO: Define conditions as when to use store words vs store packets */ + cfg->stream2mmio_cfg.store_cmd = _STREAM2MMIO_CMD_TOKEN_STORE_PACKETS; + + return true; +} + +static bool calculate_isys2401_dma_cfg( + const input_system_channel_t *channel, + const input_system_cfg_t *isys_cfg, + isys2401_dma_cfg_t *cfg) +{ + cfg->channel = channel->dma_channel; + + /* only online/sensor mode goto vmem + offline/buffered_sensor, tpg and prbs will go to ddr */ + if (isys_cfg->online) + cfg->connection = isys2401_dma_ibuf_to_vmem_connection; + else + cfg->connection = isys2401_dma_ibuf_to_ddr_connection; + + cfg->extension = isys2401_dma_zero_extension; + cfg->height = 1; + + return true; +} + +/* See also: ia_css_dma_configure_from_info() */ +static bool calculate_isys2401_dma_port_cfg( + const input_system_cfg_t *isys_cfg, + bool raw_packed, + bool metadata, + isys2401_dma_port_cfg_t *cfg) +{ + s32 bits_per_pixel; + s32 pixels_per_line; + s32 align_req_in_bytes; + + /* TODO: Move metadata away from isys_cfg to application layer */ + if (metadata) { + bits_per_pixel = isys_cfg->metadata.bits_per_pixel; + pixels_per_line = isys_cfg->metadata.pixels_per_line; + align_req_in_bytes = isys_cfg->metadata.align_req_in_bytes; + } else { + bits_per_pixel = isys_cfg->input_port_resolution.bits_per_pixel; + pixels_per_line = isys_cfg->input_port_resolution.pixels_per_line; + align_req_in_bytes = isys_cfg->input_port_resolution.align_req_in_bytes; + } + + cfg->stride = calculate_stride(bits_per_pixel, pixels_per_line, raw_packed, + align_req_in_bytes); + + if (!raw_packed) + bits_per_pixel = CEIL_MUL(bits_per_pixel, 8); + + cfg->elements = HIVE_ISP_DDR_WORD_BITS / bits_per_pixel; + cfg->cropping = 0; + cfg->width = CEIL_DIV(cfg->stride, HIVE_ISP_DDR_WORD_BYTES); + + return true; +} + +static csi_mipi_packet_type_t get_csi_mipi_packet_type( + int32_t data_type) +{ + csi_mipi_packet_type_t packet_type; + + packet_type = CSI_MIPI_PACKET_TYPE_RESERVED; + + if (data_type >= 0 && data_type <= MIPI_FORMAT_SHORT8) + packet_type = CSI_MIPI_PACKET_TYPE_SHORT; + + if (data_type > MIPI_FORMAT_SHORT8 && data_type <= N_MIPI_FORMAT) + packet_type = CSI_MIPI_PACKET_TYPE_LONG; + + return packet_type; +} + +/* end of Private Methods */ +#endif diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.h b/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.h new file mode 100644 index 000000000000..b675907791ad --- /dev/null +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/virtual_isys.h @@ -0,0 +1,24 @@ +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2010 - 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __VIRTUAL_ISYS_H_INCLUDED__ +#define __VIRTUAL_ISYS_H_INCLUDED__ + +/* cmd for storing a number of packets indicated by reg _STREAM2MMIO_NUM_ITEMS*/ +#define _STREAM2MMIO_CMD_TOKEN_STORE_PACKETS 1 + +/* command for waiting for a frame start */ +#define _STREAM2MMIO_CMD_TOKEN_SYNC_FRAME 2 + +#endif /* __VIRTUAL_ISYS_H_INCLUDED__ */ |