ais: query field info and pass to user space
Current path to query field info: SOF ISR -> tasklet -> query thread with high priority -> ba driver -> adv7481. Pass field type to user space if they are valid after verification. Change-Id: Id9926236389200446092dc9abb688ee1f83ab0c3 Signed-off-by: Andy Sun <bins@codeaurora.org>
This commit is contained in:
parent
11734d0451
commit
3375a292ea
9 changed files with 294 additions and 2 deletions
|
@ -1005,6 +1005,7 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||||
{
|
{
|
||||||
struct adv7481_state *state = to_state(sd);
|
struct adv7481_state *state = to_state(sd);
|
||||||
int *ret_val = arg;
|
int *ret_val = arg;
|
||||||
|
uint8_t status = 0;
|
||||||
long ret = 0;
|
long ret = 0;
|
||||||
int param = 0;
|
int param = 0;
|
||||||
|
|
||||||
|
@ -1039,6 +1040,22 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||||
case VIDIOC_HDMI_RX_CEC_S_ENABLE:
|
case VIDIOC_HDMI_RX_CEC_S_ENABLE:
|
||||||
ret = adv7481_cec_powerup(state, arg);
|
ret = adv7481_cec_powerup(state, arg);
|
||||||
break;
|
break;
|
||||||
|
case VIDIOC_CVBS_G_FIELD_STATUS:
|
||||||
|
/* Select SDP read-only Map 1 */
|
||||||
|
adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr,
|
||||||
|
SDP_RW_MAP_REG, 0x02);
|
||||||
|
status = adv7481_rd_byte(&state->i2c_client,
|
||||||
|
state->i2c_sdp_addr, SDP_RO_MAP_1_FIELD_ADDR);
|
||||||
|
adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr,
|
||||||
|
SDP_RW_MAP_REG, 0x00);
|
||||||
|
if (ret_val) {
|
||||||
|
*ret_val = ADV_REG_GETFIELD(status,
|
||||||
|
SDP_RO_MAP_1_EVEN_FIELD);
|
||||||
|
} else {
|
||||||
|
pr_err("%s: NULL pointer provided\n", __func__);
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
pr_err("Not a typewriter! Command: 0x%x", cmd);
|
pr_err("Not a typewriter! Command: 0x%x", cmd);
|
||||||
ret = -ENOTTY;
|
ret = -ENOTTY;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -411,6 +411,11 @@
|
||||||
#define SDP_RO_MAIN_IN_LOCK_BMSK 0x0001
|
#define SDP_RO_MAIN_IN_LOCK_BMSK 0x0001
|
||||||
#define SDP_RO_MAIN_IN_LOCK_SHFT 0
|
#define SDP_RO_MAIN_IN_LOCK_SHFT 0
|
||||||
|
|
||||||
|
/* SDP R/O Map 1 Registers */
|
||||||
|
#define SDP_RO_MAP_1_FIELD_ADDR 0x45
|
||||||
|
#define SDP_RO_MAP_1_EVEN_FIELD_BMSK 0x10
|
||||||
|
#define SDP_RO_MAP_1_EVEN_FIELD_SHFT 4
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CSI Map Registers
|
* CSI Map Registers
|
||||||
|
|
|
@ -164,6 +164,8 @@ struct msm_vfe_irq_ops {
|
||||||
void (*config_irq)(struct vfe_device *vfe_dev,
|
void (*config_irq)(struct vfe_device *vfe_dev,
|
||||||
uint32_t irq_status0, uint32_t irq_status1,
|
uint32_t irq_status0, uint32_t irq_status1,
|
||||||
enum msm_isp_irq_operation);
|
enum msm_isp_irq_operation);
|
||||||
|
void (*process_sof_irq)(struct vfe_device *vfe_dev,
|
||||||
|
uint32_t irq_status0, uint32_t irq_status1);
|
||||||
void (*process_eof_irq)(struct vfe_device *vfe_dev,
|
void (*process_eof_irq)(struct vfe_device *vfe_dev,
|
||||||
uint32_t irq_status0);
|
uint32_t irq_status0);
|
||||||
};
|
};
|
||||||
|
@ -411,6 +413,12 @@ struct msm_vfe_frame_request_queue {
|
||||||
|
|
||||||
#define MSM_VFE_REQUESTQ_SIZE 8
|
#define MSM_VFE_REQUESTQ_SIZE 8
|
||||||
|
|
||||||
|
struct msm_vfe_fields_info {
|
||||||
|
bool even_field;
|
||||||
|
struct timeval sof_ts;
|
||||||
|
struct timeval field_ts;
|
||||||
|
};
|
||||||
|
|
||||||
struct msm_vfe_axi_stream {
|
struct msm_vfe_axi_stream {
|
||||||
uint32_t frame_id;
|
uint32_t frame_id;
|
||||||
enum msm_vfe_axi_state state;
|
enum msm_vfe_axi_state state;
|
||||||
|
@ -457,6 +465,11 @@ struct msm_vfe_axi_stream {
|
||||||
enum msm_stream_memory_input_t memory_input;
|
enum msm_stream_memory_input_t memory_input;
|
||||||
struct msm_isp_sw_framskip sw_skip;
|
struct msm_isp_sw_framskip sw_skip;
|
||||||
uint8_t sw_ping_pong_bit;
|
uint8_t sw_ping_pong_bit;
|
||||||
|
|
||||||
|
bool interlaced;
|
||||||
|
struct msm_vfe_fields_info field_info[2];
|
||||||
|
uint32_t field_index;
|
||||||
|
uint32_t field_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msm_vfe_axi_composite_info {
|
struct msm_vfe_axi_composite_info {
|
||||||
|
@ -798,6 +811,12 @@ struct vfe_device {
|
||||||
/* before halt irq info */
|
/* before halt irq info */
|
||||||
uint32_t recovery_irq0_mask;
|
uint32_t recovery_irq0_mask;
|
||||||
uint32_t recovery_irq1_mask;
|
uint32_t recovery_irq1_mask;
|
||||||
|
|
||||||
|
/* interlaced field info */
|
||||||
|
void *ba_inst_hdl;
|
||||||
|
struct task_struct *field_thread_id;
|
||||||
|
wait_queue_head_t field_waitqueue;
|
||||||
|
bool wakeupflag;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vfe_parent_device {
|
struct vfe_parent_device {
|
||||||
|
|
|
@ -662,6 +662,37 @@ void msm_vfe47_process_epoch_irq(struct vfe_device *vfe_dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void msm_isp47_process_sof_irq(struct vfe_device *vfe_dev,
|
||||||
|
uint32_t irq_status0, uint32_t irq_status1)
|
||||||
|
{
|
||||||
|
int i, axi_src_idx[4], src_count = 0;
|
||||||
|
struct msm_vfe_axi_stream *pstream_info;
|
||||||
|
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
|
||||||
|
|
||||||
|
if (irq_status0 & BIT(0))
|
||||||
|
axi_src_idx[src_count++] = CAMIF_RAW;
|
||||||
|
if (irq_status1 & BIT(29))
|
||||||
|
axi_src_idx[src_count++] = RDI_INTF_0;
|
||||||
|
if (irq_status1 & BIT(30))
|
||||||
|
axi_src_idx[src_count++] = RDI_INTF_1;
|
||||||
|
if (irq_status1 & BIT(31))
|
||||||
|
axi_src_idx[src_count++] = RDI_INTF_2;
|
||||||
|
|
||||||
|
if (src_count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < src_count; i++) {
|
||||||
|
pstream_info = &axi_data->stream_info[axi_src_idx[i]];
|
||||||
|
|
||||||
|
if (pstream_info->interlaced) {
|
||||||
|
vfe_dev->wakeupflag = true;
|
||||||
|
wake_up_interruptible(&vfe_dev->field_waitqueue);
|
||||||
|
/* currently we support only 1 interlaced instance */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void msm_isp47_process_eof_irq(struct vfe_device *vfe_dev,
|
void msm_isp47_process_eof_irq(struct vfe_device *vfe_dev,
|
||||||
uint32_t irq_status0)
|
uint32_t irq_status0)
|
||||||
{
|
{
|
||||||
|
@ -2718,6 +2749,7 @@ struct msm_vfe_hardware_info vfe47_hw_info = {
|
||||||
.process_stats_irq = msm_isp_process_stats_irq,
|
.process_stats_irq = msm_isp_process_stats_irq,
|
||||||
.process_epoch_irq = msm_vfe47_process_epoch_irq,
|
.process_epoch_irq = msm_vfe47_process_epoch_irq,
|
||||||
.config_irq = msm_vfe47_config_irq,
|
.config_irq = msm_vfe47_config_irq,
|
||||||
|
.process_sof_irq = msm_isp47_process_sof_irq,
|
||||||
.process_eof_irq = msm_isp47_process_eof_irq,
|
.process_eof_irq = msm_isp47_process_eof_irq,
|
||||||
},
|
},
|
||||||
.axi_ops = {
|
.axi_ops = {
|
||||||
|
|
|
@ -2042,6 +2042,12 @@ static int msm_isp_process_done_buf(struct vfe_device *vfe_dev,
|
||||||
buf_event.u.buf_done.buf_idx = buf->buf_idx;
|
buf_event.u.buf_done.buf_idx = buf->buf_idx;
|
||||||
buf_event.u.buf_done.output_format =
|
buf_event.u.buf_done.output_format =
|
||||||
stream_info->runtime_output_format;
|
stream_info->runtime_output_format;
|
||||||
|
|
||||||
|
if (stream_info->interlaced)
|
||||||
|
buf_event.u.buf_done.field_type = stream_info->field_type;
|
||||||
|
else
|
||||||
|
buf_event.u.buf_done.field_type = 0;
|
||||||
|
|
||||||
if (vfe_dev->fetch_engine_info.is_busy &&
|
if (vfe_dev->fetch_engine_info.is_busy &&
|
||||||
SRC_TO_INTF(stream_info->stream_src) == VFE_PIX_0) {
|
SRC_TO_INTF(stream_info->stream_src) == VFE_PIX_0) {
|
||||||
vfe_dev->fetch_engine_info.is_busy = 0;
|
vfe_dev->fetch_engine_info.is_busy = 0;
|
||||||
|
@ -3132,6 +3138,7 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
stream_info->interlaced = false;
|
||||||
vfe_dev->reg_update_requested &=
|
vfe_dev->reg_update_requested &=
|
||||||
~(BIT(SRC_TO_INTF(stream_info->stream_src)));
|
~(BIT(SRC_TO_INTF(stream_info->stream_src)));
|
||||||
}
|
}
|
||||||
|
@ -3544,13 +3551,18 @@ int msm_isp_axi_output_cfg(struct vfe_device *vfe_dev, void *arg)
|
||||||
INIT_LIST_HEAD(&pstream_info->request_q);
|
INIT_LIST_HEAD(&pstream_info->request_q);
|
||||||
|
|
||||||
pstream_info->frame_based =
|
pstream_info->frame_based =
|
||||||
pCmd->output_path_cfg[axi_src_idx].frame_based;
|
pCmd->output_path_cfg[axi_src_idx].frame_based & BIT(0);
|
||||||
|
pstream_info->interlaced =
|
||||||
|
(pCmd->output_path_cfg[axi_src_idx].frame_based
|
||||||
|
& BIT(INTERLACE_OFFSET)) ? true : false;
|
||||||
|
|
||||||
/* send buffers to user through vfe dev node */
|
/* send buffers to user through vfe dev node */
|
||||||
pstream_info->buf_divert = 1;
|
pstream_info->buf_divert = 1;
|
||||||
pstream_info->output_format =
|
pstream_info->output_format =
|
||||||
pCmd->output_path_cfg[axi_src_idx].format;
|
pCmd->output_path_cfg[axi_src_idx].format;
|
||||||
|
|
||||||
|
pstream_info->field_index = 0;
|
||||||
|
|
||||||
msm_isp_axi_get_num_planes(
|
msm_isp_axi_get_num_planes(
|
||||||
pCmd->output_path_cfg[axi_src_idx].format,
|
pCmd->output_path_cfg[axi_src_idx].format,
|
||||||
pstream_info);
|
pstream_info);
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <media/v4l2-subdev.h>
|
#include <media/v4l2-subdev.h>
|
||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
|
#include <linux/kthread.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
|
||||||
#include "msm.h"
|
#include "msm.h"
|
||||||
#include "msm_isp_util.h"
|
#include "msm_isp_util.h"
|
||||||
|
@ -23,6 +25,7 @@
|
||||||
#include "cam_smmu_api.h"
|
#include "cam_smmu_api.h"
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include "trace/events/msm_cam.h"
|
#include "trace/events/msm_cam.h"
|
||||||
|
#include "media/msm_ba.h"
|
||||||
|
|
||||||
#define MAX_ISP_V4l2_EVENTS 100
|
#define MAX_ISP_V4l2_EVENTS 100
|
||||||
#define MAX_ISP_REG_LIST 100
|
#define MAX_ISP_REG_LIST 100
|
||||||
|
@ -1974,6 +1977,166 @@ void msm_isp_reset_burst_count_and_frame_drop(
|
||||||
msm_isp_reset_framedrop(vfe_dev, stream_info);
|
msm_isp_reset_framedrop(vfe_dev, stream_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void msm_isp_field_type_read_thread(void *data)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
uint8_t i, j = 0;
|
||||||
|
bool even_field = 0;
|
||||||
|
uint64_t timestamp_us[4];
|
||||||
|
struct msm_isp_timestamp ts;
|
||||||
|
struct msm_vfe_axi_stream *stream_info = NULL;
|
||||||
|
struct vfe_device *vfe_dev = (struct vfe_device *)data;
|
||||||
|
|
||||||
|
pr_debug("Enter field_type_read_thread\n");
|
||||||
|
|
||||||
|
vfe_dev->ba_inst_hdl = msm_ba_open(NULL);
|
||||||
|
if (vfe_dev->ba_inst_hdl == NULL) {
|
||||||
|
pr_err("%s: ba open failed\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!kthread_should_stop()) {
|
||||||
|
ret = 0;
|
||||||
|
wait_event_interruptible(vfe_dev->field_waitqueue,
|
||||||
|
vfe_dev->wakeupflag == true);
|
||||||
|
if (kthread_should_stop()) {
|
||||||
|
pr_debug("%s: field thread has stopped\n", __func__);
|
||||||
|
goto bs_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < VFE_AXI_SRC_MAX; i++) {
|
||||||
|
if (vfe_dev->axi_data.stream_info[i].interlaced)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == VFE_AXI_SRC_MAX) {
|
||||||
|
vfe_dev->wakeupflag = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_info = &vfe_dev->axi_data.stream_info[i];
|
||||||
|
j = stream_info->field_index;
|
||||||
|
|
||||||
|
/* Detect field status from bridge chip */
|
||||||
|
ret = msm_ba_private_ioctl(vfe_dev->ba_inst_hdl,
|
||||||
|
VIDIOC_CVBS_G_FIELD_STATUS, &even_field);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: get field status failed: %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
} else {
|
||||||
|
msm_isp_get_timestamp(&ts, vfe_dev);
|
||||||
|
stream_info->field_info[j%2].even_field = even_field;
|
||||||
|
stream_info->field_info[j%2].field_ts.tv_sec =
|
||||||
|
ts.buf_time.tv_sec;
|
||||||
|
stream_info->field_info[j%2].field_ts.tv_usec =
|
||||||
|
ts.buf_time.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_info->field_index++;
|
||||||
|
|
||||||
|
/* once 2 fields info getting done, do the verification */
|
||||||
|
if (stream_info->field_index%2 == 0) {
|
||||||
|
timestamp_us[0] =
|
||||||
|
stream_info->field_info[0].sof_ts.tv_sec
|
||||||
|
* 1000 * 1000
|
||||||
|
+ stream_info->field_info[0].sof_ts.tv_usec;
|
||||||
|
timestamp_us[1] =
|
||||||
|
stream_info->field_info[0].field_ts.tv_sec
|
||||||
|
* 1000 * 1000
|
||||||
|
+ stream_info->field_info[0].field_ts.tv_usec;
|
||||||
|
timestamp_us[2] =
|
||||||
|
stream_info->field_info[1].sof_ts.tv_sec
|
||||||
|
* 1000 * 1000
|
||||||
|
+ stream_info->field_info[1].sof_ts.tv_usec;
|
||||||
|
timestamp_us[3] =
|
||||||
|
stream_info->field_info[1].field_ts.tv_sec
|
||||||
|
* 1000 * 1000
|
||||||
|
+ stream_info->field_info[1].field_ts.tv_usec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expected timing:
|
||||||
|
* field 0 SOF -> field 0 type read ->
|
||||||
|
* field 1 SOF -> field 1 type read
|
||||||
|
*/
|
||||||
|
if ((timestamp_us[0] < timestamp_us[1]) &&
|
||||||
|
(timestamp_us[2] < timestamp_us[3]) &&
|
||||||
|
(timestamp_us[1] < timestamp_us[2]) &&
|
||||||
|
(stream_info->field_info[0].even_field !=
|
||||||
|
stream_info->field_info[1].even_field)) {
|
||||||
|
/*
|
||||||
|
* Field type:
|
||||||
|
* 0 - unknown
|
||||||
|
* 1 - odd first
|
||||||
|
* 2 - even first
|
||||||
|
*/
|
||||||
|
stream_info->field_type =
|
||||||
|
stream_info->field_info[0].even_field ?
|
||||||
|
2 : 1;
|
||||||
|
} else {
|
||||||
|
stream_info->field_type = 0;
|
||||||
|
pr_err("Field: %llu %llu %llu %llu %d %d\n",
|
||||||
|
timestamp_us[0], timestamp_us[1],
|
||||||
|
timestamp_us[2], timestamp_us[3],
|
||||||
|
stream_info->field_info[0].even_field,
|
||||||
|
stream_info->field_info[1].even_field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vfe_dev->wakeupflag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bs_close:
|
||||||
|
ret = msm_ba_close(vfe_dev->ba_inst_hdl);
|
||||||
|
if (ret)
|
||||||
|
pr_err("%s: msm ba close failed\n", __func__);
|
||||||
|
vfe_dev->ba_inst_hdl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msm_isp_init_field_type_kthread(struct vfe_device *vfe_dev)
|
||||||
|
{
|
||||||
|
init_waitqueue_head(&vfe_dev->field_waitqueue);
|
||||||
|
|
||||||
|
ISP_DBG("%s: Queue initialized\n", __func__);
|
||||||
|
vfe_dev->field_thread_id = kthread_run(
|
||||||
|
(void *)msm_isp_field_type_read_thread,
|
||||||
|
(void *)vfe_dev, "field_type_kthread");
|
||||||
|
if (IS_ERR(vfe_dev->field_thread_id)) {
|
||||||
|
pr_err("%s: Unable to run the thread\n", __func__);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void msm_isp_field_timestamp(struct vfe_device *vfe_dev,
|
||||||
|
uint32_t irq_status0, uint32_t irq_status1,
|
||||||
|
struct timeval *timestamp)
|
||||||
|
{
|
||||||
|
uint8_t i, j = 0;
|
||||||
|
struct msm_vfe_axi_stream *stream_info = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < VFE_AXI_SRC_MAX; i++) {
|
||||||
|
if (vfe_dev->axi_data.stream_info[i].interlaced)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == VFE_AXI_SRC_MAX)
|
||||||
|
return;
|
||||||
|
|
||||||
|
stream_info = &vfe_dev->axi_data.stream_info[i];
|
||||||
|
|
||||||
|
/* SOF timestamp */
|
||||||
|
if (((i == CAMIF_RAW) && (irq_status0 & BIT(0)))
|
||||||
|
|| ((i == RDI_INTF_0) && (irq_status1 & BIT(29)))
|
||||||
|
|| ((i == RDI_INTF_1) && (irq_status1 & BIT(30)))
|
||||||
|
|| ((i == RDI_INTF_2) && (irq_status1 & BIT(31)))) {
|
||||||
|
j = stream_info->field_index;
|
||||||
|
stream_info->field_info[j%2].sof_ts.tv_sec =
|
||||||
|
timestamp->tv_sec;
|
||||||
|
stream_info->field_info[j%2].sof_ts.tv_usec =
|
||||||
|
timestamp->tv_usec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev,
|
static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev,
|
||||||
uint32_t irq_status0, uint32_t irq_status1,
|
uint32_t irq_status0, uint32_t irq_status1,
|
||||||
uint32_t ping_pong_status)
|
uint32_t ping_pong_status)
|
||||||
|
@ -1999,6 +2162,10 @@ static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev,
|
||||||
MSM_VFE_TASKLETQ_SIZE;
|
MSM_VFE_TASKLETQ_SIZE;
|
||||||
list_add_tail(&queue_cmd->list, &vfe_dev->tasklet_q);
|
list_add_tail(&queue_cmd->list, &vfe_dev->tasklet_q);
|
||||||
spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
|
spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
|
||||||
|
|
||||||
|
msm_isp_field_timestamp(vfe_dev, irq_status0, irq_status1,
|
||||||
|
&queue_cmd->ts.buf_time);
|
||||||
|
|
||||||
tasklet_schedule(&vfe_dev->vfe_tasklet);
|
tasklet_schedule(&vfe_dev->vfe_tasklet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2121,6 +2288,7 @@ void msm_isp_do_tasklet(unsigned long data)
|
||||||
spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
|
spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
|
||||||
ISP_DBG("%s: vfe_id %d status0: 0x%x status1: 0x%x\n",
|
ISP_DBG("%s: vfe_id %d status0: 0x%x status1: 0x%x\n",
|
||||||
__func__, vfe_dev->pdev->id, irq_status0, irq_status1);
|
__func__, vfe_dev->pdev->id, irq_status0, irq_status1);
|
||||||
|
|
||||||
if (vfe_dev->is_split) {
|
if (vfe_dev->is_split) {
|
||||||
spin_lock(&dump_tasklet_lock);
|
spin_lock(&dump_tasklet_lock);
|
||||||
tasklet_data.arr[tasklet_data.first].
|
tasklet_data.arr[tasklet_data.first].
|
||||||
|
@ -2139,6 +2307,8 @@ void msm_isp_do_tasklet(unsigned long data)
|
||||||
(tasklet_data.first + 1) % MAX_ISP_PING_PONG_DUMP_SIZE;
|
(tasklet_data.first + 1) % MAX_ISP_PING_PONG_DUMP_SIZE;
|
||||||
spin_unlock(&dump_tasklet_lock);
|
spin_unlock(&dump_tasklet_lock);
|
||||||
}
|
}
|
||||||
|
irq_ops->process_sof_irq(vfe_dev,
|
||||||
|
irq_status0, irq_status1);
|
||||||
irq_ops->process_reset_irq(vfe_dev,
|
irq_ops->process_reset_irq(vfe_dev,
|
||||||
irq_status0, irq_status1);
|
irq_status0, irq_status1);
|
||||||
irq_ops->process_halt_irq(vfe_dev,
|
irq_ops->process_halt_irq(vfe_dev,
|
||||||
|
@ -2291,8 +2461,17 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||||
cam_smmu_reg_client_page_fault_handler(
|
cam_smmu_reg_client_page_fault_handler(
|
||||||
vfe_dev->buf_mgr->iommu_hdl,
|
vfe_dev->buf_mgr->iommu_hdl,
|
||||||
msm_vfe_iommu_fault_handler, vfe_dev);
|
msm_vfe_iommu_fault_handler, vfe_dev);
|
||||||
|
|
||||||
|
/* to detect interlaced frame type through ba driver */
|
||||||
|
rc = msm_isp_init_field_type_kthread(vfe_dev);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("%s: init field thread failed\n", __func__);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&vfe_dev->core_mutex);
|
mutex_unlock(&vfe_dev->core_mutex);
|
||||||
mutex_unlock(&vfe_dev->realtime_mutex);
|
mutex_unlock(&vfe_dev->realtime_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2361,6 +2540,9 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||||
}
|
}
|
||||||
vfe_dev->is_split = 0;
|
vfe_dev->is_split = 0;
|
||||||
|
|
||||||
|
vfe_dev->wakeupflag = true;
|
||||||
|
kthread_stop(vfe_dev->field_thread_id);
|
||||||
|
|
||||||
mutex_unlock(&vfe_dev->core_mutex);
|
mutex_unlock(&vfe_dev->core_mutex);
|
||||||
mutex_unlock(&vfe_dev->realtime_mutex);
|
mutex_unlock(&vfe_dev->realtime_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -555,6 +555,24 @@ long msm_ba_private_ioctl(void *instance, int cmd, void *arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case VIDIOC_CVBS_G_FIELD_STATUS: {
|
||||||
|
dprintk(BA_DBG, "VIDIOC_CVBS_G_FIELD_STATUS");
|
||||||
|
sd = inst->sd;
|
||||||
|
if (!sd) {
|
||||||
|
dprintk(BA_ERR, "No sd registered");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (s_ioctl) {
|
||||||
|
rc = v4l2_subdev_call(sd, core, ioctl, cmd, s_ioctl);
|
||||||
|
if (rc)
|
||||||
|
dprintk(BA_ERR, "%s failed: %ld on cmd: 0x%x",
|
||||||
|
__func__, rc, cmd);
|
||||||
|
} else {
|
||||||
|
dprintk(BA_ERR, "%s: NULL argument provided", __func__);
|
||||||
|
rc = -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dprintk(BA_WARN, "Not a typewriter! Command: 0x%x", cmd);
|
dprintk(BA_WARN, "Not a typewriter! Command: 0x%x", cmd);
|
||||||
rc = -ENOTTY;
|
rc = -ENOTTY;
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
#include <media/v4l2-device.h>
|
#include <media/v4l2-device.h>
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
|
|
||||||
|
/* Control ID to fetch register Values */
|
||||||
|
#define VIDIOC_CVBS_G_FIELD_STATUS _IOR('V', BASE_VIDIOC_PRIVATE + 5, int)
|
||||||
|
|
||||||
enum msm_ba_ip {
|
enum msm_ba_ip {
|
||||||
BA_IP_CVBS_0 = 0,
|
BA_IP_CVBS_0 = 0,
|
||||||
BA_IP_CVBS_1,
|
BA_IP_CVBS_1,
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
|
|
||||||
#define ISP_STATS_STREAM_BIT 0x80000000
|
#define ISP_STATS_STREAM_BIT 0x80000000
|
||||||
|
|
||||||
|
#define INTERLACE_SUPPORT
|
||||||
|
#define INTERLACE_OFFSET (1)
|
||||||
|
|
||||||
struct msm_vfe_cfg_cmd_list;
|
struct msm_vfe_cfg_cmd_list;
|
||||||
|
|
||||||
enum ISP_START_PIXEL_PATTERN {
|
enum ISP_START_PIXEL_PATTERN {
|
||||||
|
@ -733,6 +736,7 @@ struct msm_isp_buf_event {
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
uint32_t output_format;
|
uint32_t output_format;
|
||||||
int8_t buf_idx;
|
int8_t buf_idx;
|
||||||
|
uint8_t field_type;
|
||||||
};
|
};
|
||||||
struct msm_isp_fetch_eng_event {
|
struct msm_isp_fetch_eng_event {
|
||||||
uint32_t session_id;
|
uint32_t session_id;
|
||||||
|
|
Loading…
Add table
Reference in a new issue