blob: c0ba7abeb00a277dd44052869854636581d409d0 [file] [log] [blame]
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that 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 __MSM_ISP_AXI_UTIL_H__
#define __MSM_ISP_AXI_UTIL_H__
#include "msm_isp.h"
#define HANDLE_TO_IDX(handle) (handle & 0xFF)
#define SRC_TO_INTF(src) \
((src < RDI_INTF_0 || src == VFE_AXI_SRC_MAX) ? VFE_PIX_0 : \
(VFE_RAW_0 + src - RDI_INTF_0))
int msm_isp_axi_check_stream_state(
struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd);
void msm_isp_reset_framedrop(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info);
int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg);
void msm_isp_start_avtimer(void);
void msm_isp_get_avtimer_ts(struct msm_isp_timestamp *time_stamp);
int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg);
int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg);
int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg);
void msm_isp_axi_cfg_update(struct vfe_device *vfe_dev,
enum msm_vfe_input_src frame_src);
int msm_isp_axi_halt(struct vfe_device *vfe_dev,
struct msm_vfe_axi_halt_cmd *halt_cmd);
int msm_isp_axi_reset(struct vfe_device *vfe_dev,
struct msm_vfe_axi_reset_cmd *reset_cmd);
int msm_isp_axi_restart(struct vfe_device *vfe_dev,
struct msm_vfe_axi_restart_cmd *restart_cmd);
void msm_isp_axi_stream_update(struct vfe_device *vfe_dev,
enum msm_vfe_input_src frame_src,
struct msm_isp_timestamp *ts);
void msm_isp_process_reg_upd_epoch_irq(struct vfe_device *vfe_dev,
enum msm_vfe_input_src frame_src,
enum msm_isp_comp_irq_types irq,
struct msm_isp_timestamp *ts);
void msm_isp_notify(struct vfe_device *vfe_dev, uint32_t event_type,
enum msm_vfe_input_src frame_src, struct msm_isp_timestamp *ts);
void msm_isp_process_axi_irq(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1,
struct msm_isp_timestamp *ts);
void msm_isp_axi_disable_all_wm(struct vfe_device *vfe_dev);
int msm_isp_print_ping_pong_address(struct vfe_device *vfe_dev,
unsigned long fault_addr);
void msm_isp_increment_frame_id(struct vfe_device *vfe_dev,
enum msm_vfe_input_src frame_src, struct msm_isp_timestamp *ts);
int msm_isp_drop_frame(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info, struct msm_isp_timestamp *ts,
struct msm_isp_sof_info *sof_info);
void msm_isp_halt(struct vfe_device *vfe_dev);
void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event);
void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info,
uint32_t pingpong_status,
struct msm_isp_timestamp *ts);
void msm_isp_release_all_axi_stream(struct vfe_device *vfe_dev);
void msm_isp_axi_free_wm(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info);
void msm_isp_check_for_output_error(struct vfe_device *vfe_dev,
struct msm_isp_timestamp *ts, struct msm_isp_sof_info *sof_info);
static inline int msm_isp_get_vfe_idx_for_stream_user(
struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info)
{
int vfe_idx;
for (vfe_idx = 0; vfe_idx < stream_info->num_isp; vfe_idx++) {
if (stream_info->vfe_dev[vfe_idx] == vfe_dev)
return vfe_idx;
}
return -ENOTTY;
}
static inline int msm_isp_get_vfe_idx_for_stream(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info)
{
int vfe_idx = msm_isp_get_vfe_idx_for_stream_user(vfe_dev, stream_info);
if (vfe_idx < 0) {
WARN(1, "%s vfe index misssing for stream %d, vfe %d\n",
__func__, stream_info->stream_src, vfe_dev->pdev->id);
vfe_idx = 0;
}
return vfe_idx;
}
static inline void msm_isp_cfg_wm_scratch(struct vfe_device *vfe_dev,
int wm,
uint32_t pingpong_bit)
{
vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
vfe_dev->vfe_base, wm,
pingpong_bit, vfe_dev->buf_mgr->scratch_buf_addr, 0);
}
static inline void msm_isp_cfg_stream_scratch(
struct msm_vfe_axi_stream *stream_info,
uint32_t pingpong_status)
{
int i;
int j;
uint32_t pingpong_bit;
int vfe_idx;
pingpong_bit = (~(pingpong_status >> stream_info->wm[0][0]) & 0x1);
for (i = 0; i < stream_info->num_planes; i++) {
for (j = 0; j < stream_info->num_isp; j++) {
vfe_idx = msm_isp_get_vfe_idx_for_stream(
stream_info->vfe_dev[j], stream_info);
msm_isp_cfg_wm_scratch(stream_info->vfe_dev[j],
stream_info->wm[vfe_idx][i],
~pingpong_bit);
}
}
stream_info->buf[pingpong_bit] = NULL;
}
static inline struct msm_vfe_axi_stream *msm_isp_get_stream_common_data(
struct vfe_device *vfe_dev, uint32_t stream_idx)
{
struct msm_vfe_common_dev_data *common_data = vfe_dev->common_data;
struct msm_vfe_axi_stream *stream_info;
if (stream_idx >= VFE_AXI_SRC_MAX) {
pr_err("invalid stream_idx %d\n", stream_idx);
return NULL;
}
if (vfe_dev->is_split && stream_idx < RDI_INTF_0)
stream_info = &common_data->streams[stream_idx];
else
stream_info = &common_data->streams[VFE_AXI_SRC_MAX *
vfe_dev->pdev->id + stream_idx];
return stream_info;
}
static inline struct msm_vfe_axi_stream *msm_isp_vfe_get_stream(
struct dual_vfe_resource *dual_vfe_res,
int vfe_id, uint32_t index)
{
return msm_isp_get_stream_common_data(dual_vfe_res->vfe_dev[vfe_id],
index);
}
int msm_isp_cfg_offline_ping_pong_address(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status,
uint32_t buf_idx);
int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev,
void *arg);
#endif /* __MSM_ISP_AXI_UTIL_H__ */