| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * 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 <linux/string.h> /* for memcpy() */ |
| |
| #include "system_global.h" |
| |
| #ifdef ISP2401 |
| |
| #include "ia_css_isys.h" |
| #include "ia_css_debug.h" |
| #include "math_support.h" |
| #include "virtual_isys.h" |
| #include "isp.h" |
| #include "sh_css_defs.h" |
| |
| /************************************************* |
| * |
| * Forwarded Declaration |
| * |
| *************************************************/ |
| |
| static bool create_input_system_channel( |
| isp2401_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( |
| isp2401_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, |
| isp2401_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, |
| isp2401_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, |
| isp2401_ib_buffer_t *buf); |
| |
| static void release_ib_buffer( |
| isp2401_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, |
| isp2401_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, |
| isp2401_input_system_cfg_t *isys_cfg, |
| pixelgen_prbs_cfg_t *cfg); |
| |
| static bool calculate_fe_cfg( |
| const isp2401_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 isp2401_input_system_cfg_t *isys_cfg, |
| bool metadata, |
| csi_rx_backend_cfg_t *cfg); |
| |
| static bool calculate_stream2mmio_cfg( |
| const isp2401_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 isp2401_input_system_cfg_t *isys_cfg, |
| ibuf_ctrl_cfg_t *cfg); |
| |
| static bool calculate_isys2401_dma_cfg( |
| const input_system_channel_t *channel, |
| const isp2401_input_system_cfg_t *isys_cfg, |
| isys2401_dma_cfg_t *cfg); |
| |
| static bool calculate_isys2401_dma_port_cfg( |
| const isp2401_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) |
| return false; |
| |
| rc = create_input_system_channel(isys_stream_descr, false, |
| &isys_stream->channel); |
| if (!rc) { |
| 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) { |
| 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) |
| 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) |
| 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) |
| 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( |
| isp2401_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( |
| isp2401_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, |
| isp2401_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, |
| isp2401_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, |
| isp2401_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( |
| isp2401_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, |
| isp2401_input_system_cfg_t *isys_cfg, |
| pixelgen_tpg_cfg_t *cfg) |
| { |
| memcpy(cfg, &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, |
| isp2401_input_system_cfg_t *isys_cfg, |
| pixelgen_prbs_cfg_t *cfg) |
| { |
| memcpy(cfg, &isys_cfg->prbs_port_attr, sizeof(pixelgen_prbs_cfg_t)); |
| |
| return true; |
| } |
| |
| static bool calculate_fe_cfg( |
| const isp2401_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 isp2401_input_system_cfg_t *isys_cfg, |
| bool metadata, |
| csi_rx_backend_cfg_t *cfg) |
| { |
| memcpy(&cfg->lut_entry, |
| metadata ? &input_port->metadata.backend_lut_entry : |
| &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 isp2401_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 isp2401_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 isp2401_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 isp2401_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 |