699 lines
18 KiB
C
Executable file
699 lines
18 KiB
C
Executable file
/*
|
|
* Samsung Exynos SoC series FIMC-IS driver
|
|
*
|
|
* exynos5 fimc-is group manager functions
|
|
*
|
|
* Copyright (c) 2016 Samsung Electronics Co., Ltd
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/device.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/slab.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/pgtable.h>
|
|
#include <linux/firmware.h>
|
|
#include <linux/dma-mapping.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/videodev2.h>
|
|
#include <videodev2_exynos_camera.h>
|
|
#include <linux/v4l2-mediabus.h>
|
|
#include <linux/bug.h>
|
|
|
|
#include "is-hw.h"
|
|
#include "is-core.h"
|
|
#include "is-type.h"
|
|
#include "is-err.h"
|
|
#include "is-video.h"
|
|
#include "is-framemgr.h"
|
|
#include "is-groupmgr.h"
|
|
#include "is-devicemgr.h"
|
|
#include "is-device-ischain.h"
|
|
#include "is-hw.h"
|
|
#include "interface/is-interface-library.h"
|
|
|
|
#ifdef CONFIG_USE_SENSOR_GROUP
|
|
struct is_group *get_ischain_leader_group(struct is_device_ischain *device)
|
|
{
|
|
struct is_group *leader_group;
|
|
|
|
leader_group = device->groupmgr->leader[device->instance];
|
|
|
|
if ((leader_group->device_type == IS_DEVICE_SENSOR)
|
|
&& (leader_group->next)
|
|
&& (!test_bit(IS_GROUP_OTF_INPUT, &leader_group->next->state))) {
|
|
leader_group = leader_group->next;
|
|
}
|
|
|
|
return leader_group;
|
|
}
|
|
|
|
static void do_sensor_tag(unsigned long data)
|
|
{
|
|
int ret = 0;
|
|
u32 stream;
|
|
unsigned long framemgr_flag;
|
|
struct is_framemgr *framemgr;
|
|
struct v4l2_subdev *subdev;
|
|
struct camera2_node ldr_node = {0, };
|
|
struct is_device_sensor *sensor;
|
|
struct devicemgr_sensor_tag_data *tag_data;
|
|
struct is_group *group;
|
|
struct is_frame *frame;
|
|
struct is_group_task *gtask;
|
|
|
|
tag_data = (struct devicemgr_sensor_tag_data *)data;
|
|
stream = tag_data->stream;
|
|
sensor = tag_data->devicemgr->sensor[stream];
|
|
group = tag_data->group;
|
|
subdev = sensor->subdev_csi;
|
|
gtask = &sensor->groupmgr->gtask[group->id];
|
|
|
|
mgrdbgs(5, "start sensor tag(%s)\n", group->device, group, tag_data,
|
|
in_softirq() ? "S" : "H");
|
|
|
|
if (unlikely(test_bit(IS_GROUP_FORCE_STOP, &group->state))) {
|
|
mgwarn(" cancel by fstop", group, group);
|
|
goto p_err;
|
|
}
|
|
|
|
if (unlikely(test_bit(IS_GTASK_REQUEST_STOP, >ask->state))) {
|
|
mgerr(" cancel by gstop", group, group);
|
|
goto p_err;
|
|
}
|
|
|
|
framemgr = GET_HEAD_GROUP_FRAMEMGR(group, tag_data->cur_shot_idx);
|
|
if (!framemgr) {
|
|
merr("framemgr is NULL", group);
|
|
return;
|
|
}
|
|
|
|
framemgr_e_barrier_irqs(framemgr, 0, framemgr_flag);
|
|
frame = find_frame(framemgr, FS_PROCESS, frame_fcount, (void *)(ulong)tag_data->fcount);
|
|
|
|
if (!frame) {
|
|
frame_manager_print_queues(framemgr);
|
|
merr("[F%d] There's no frame in processing." \
|
|
"Can't sync sensor and ischain buffer anymore..",
|
|
group, tag_data->fcount);
|
|
framemgr_x_barrier_irqr(framemgr, 0, framemgr_flag);
|
|
return;
|
|
}
|
|
framemgr_x_barrier_irqr(framemgr, 0, framemgr_flag);
|
|
|
|
ldr_node = frame->shot_ext->node_group.leader;
|
|
|
|
ret = is_sensor_group_tag(sensor, frame, &ldr_node);
|
|
if (ret) {
|
|
merr("is_sensor_group_tag is fail(%d)", group, ret);
|
|
goto p_err;
|
|
}
|
|
|
|
mgrdbgs(5, "finish sensor tag(%s)\n", group->device, group, tag_data,
|
|
in_softirq() ? "S" : "H");
|
|
|
|
p_err:
|
|
return;
|
|
}
|
|
|
|
int is_devicemgr_probe(struct is_devicemgr *devicemgr)
|
|
{
|
|
int ret = 0;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int is_devicemgr_open(struct is_devicemgr *devicemgr,
|
|
void *device, enum is_device_type type)
|
|
{
|
|
int ret = 0;
|
|
u32 stream = 0;
|
|
u32 group_id;
|
|
struct is_core *core;
|
|
struct is_group *group = NULL;
|
|
struct is_device_sensor *sensor;
|
|
struct is_device_ischain *ischain;
|
|
|
|
FIMC_BUG(!devicemgr);
|
|
FIMC_BUG(!device);
|
|
|
|
switch (type) {
|
|
case IS_DEVICE_SENSOR:
|
|
sensor = (struct is_device_sensor *)device;
|
|
group = &sensor->group_sensor;
|
|
core = sensor->private_data;
|
|
|
|
FIMC_BUG(!core);
|
|
FIMC_BUG(!group);
|
|
FIMC_BUG(!sensor->vctx);
|
|
FIMC_BUG(!GET_VIDEO(sensor->vctx));
|
|
|
|
/* get the stream id */
|
|
for (stream = 0; stream < IS_STREAM_COUNT; ++stream) {
|
|
ischain = &core->ischain[stream];
|
|
if (!test_bit(IS_ISCHAIN_OPEN, &ischain->state))
|
|
break;
|
|
}
|
|
|
|
FIMC_BUG(stream >= IS_STREAM_COUNT);
|
|
|
|
/* init group's device information */
|
|
devicemgr->sensor[stream] = sensor;
|
|
sensor->instance = stream;
|
|
group->instance = stream;
|
|
group->device = ischain;
|
|
group_id = GROUP_ID_SS0 + GET_SSX_ID(GET_VIDEO(sensor->vctx));
|
|
|
|
ret = is_group_open(sensor->groupmgr,
|
|
group,
|
|
group_id,
|
|
sensor->vctx);
|
|
if (ret) {
|
|
merr("is_group_open is fail(%d)", ischain, ret);
|
|
ret = -EINVAL;
|
|
goto p_err;
|
|
}
|
|
|
|
sensor->vctx->next_device = ischain;
|
|
break;
|
|
case IS_DEVICE_ISCHAIN:
|
|
ischain = (struct is_device_ischain *)device;
|
|
stream = ischain->instance;
|
|
|
|
devicemgr->ischain[stream] = ischain;
|
|
break;
|
|
default:
|
|
err("device type(%d) is invalid", type);
|
|
BUG();
|
|
break;
|
|
}
|
|
|
|
p_err:
|
|
return ret;
|
|
}
|
|
|
|
int is_devicemgr_binding(struct is_devicemgr *devicemgr,
|
|
struct is_device_sensor *sensor,
|
|
struct is_device_ischain *ischain,
|
|
enum is_device_type type)
|
|
{
|
|
int ret = 0;
|
|
struct is_group *group = NULL;
|
|
struct is_group *child_group;
|
|
|
|
switch (type) {
|
|
case IS_DEVICE_SENSOR:
|
|
if (test_bit(IS_SENSOR_ONLY, &sensor->state)) {
|
|
/* in case of sensor driving */
|
|
ischain->sensor = sensor;
|
|
sensor->ischain = ischain;
|
|
|
|
/* Clear ischain device all state */
|
|
ischain->state = 0;
|
|
|
|
/*
|
|
* Forcely set the ischain's state to "Opened"
|
|
* Because if it's sensor driving mode, ischain was not opened from HAL.
|
|
*/
|
|
set_bit(IS_ISCHAIN_OPEN, &ischain->state);
|
|
set_bit(ischain->instance, &ischain->ginstance_map);
|
|
|
|
ret = is_groupmgr_init(sensor->groupmgr, ischain);
|
|
if (ret) {
|
|
merr("is_groupmgr_init is fail(%d)", ischain, ret);
|
|
ret = -EINVAL;
|
|
goto p_err;
|
|
}
|
|
}
|
|
break;
|
|
case IS_DEVICE_ISCHAIN:
|
|
if (sensor &&
|
|
!test_bit(IS_ISCHAIN_REPROCESSING, &ischain->state)) {
|
|
group = &sensor->group_sensor;
|
|
FIMC_BUG(group->instance != ischain->instance);
|
|
|
|
child_group = GET_HEAD_GROUP_IN_DEVICE(IS_DEVICE_ISCHAIN, group);
|
|
if (child_group) {
|
|
info("[%d/%d] sensor otf output set\n",
|
|
sensor->device_id, ischain->instance);
|
|
set_bit(IS_SENSOR_OTF_OUTPUT, &sensor->state);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
err("device type(%d) is invalid", type);
|
|
BUG();
|
|
break;
|
|
}
|
|
|
|
p_err:
|
|
return ret;
|
|
}
|
|
|
|
int is_devicemgr_start(struct is_devicemgr *devicemgr,
|
|
void *device, enum is_device_type type)
|
|
{
|
|
int ret = 0;
|
|
struct is_group *group;
|
|
struct is_device_sensor *sensor;
|
|
|
|
switch (type) {
|
|
case IS_DEVICE_SENSOR:
|
|
sensor = (struct is_device_sensor *)device;
|
|
group = &sensor->group_sensor;
|
|
|
|
if (!test_bit(IS_SENSOR_ONLY, &sensor->state) && sensor->ischain) {
|
|
ret = is_ischain_start_wrap(sensor->ischain, group);
|
|
if (ret) {
|
|
merr("is_ischain_start_wrap is fail(%d)", sensor->ischain, ret);
|
|
ret = -EINVAL;
|
|
goto p_err;
|
|
}
|
|
} else {
|
|
ret = is_groupmgr_start(sensor->groupmgr, group->device);
|
|
if (ret) {
|
|
merr("is_groupmgr_start is fail(%d)", group->device, ret);
|
|
ret = -EINVAL;
|
|
goto p_err;
|
|
}
|
|
}
|
|
|
|
if (IS_ENABLED(CHAIN_TAG_SENSOR_IN_SOFTIRQ_CONTEXT)) {
|
|
struct is_group *child_group
|
|
= GET_HEAD_GROUP_IN_DEVICE(IS_DEVICE_ISCHAIN, group);
|
|
|
|
/* only in case of OTF case, uses tasklet. */
|
|
if (sensor->ischain && child_group)
|
|
tasklet_init(&devicemgr->tasklet[group->instance], do_sensor_tag,
|
|
(unsigned long)&devicemgr->tag_data[group->instance]);
|
|
}
|
|
break;
|
|
case IS_DEVICE_ISCHAIN:
|
|
break;
|
|
default:
|
|
err("device type(%d) is invalid", type);
|
|
BUG();
|
|
break;
|
|
}
|
|
|
|
p_err:
|
|
return ret;
|
|
}
|
|
|
|
int is_devicemgr_stop(struct is_devicemgr *devicemgr,
|
|
void *device, enum is_device_type type)
|
|
{
|
|
int ret = 0;
|
|
struct is_group *group;
|
|
struct is_device_sensor *sensor;
|
|
|
|
switch (type) {
|
|
case IS_DEVICE_SENSOR:
|
|
sensor = (struct is_device_sensor *)device;
|
|
group = &sensor->group_sensor;
|
|
|
|
if (IS_ENABLED(CHAIN_TAG_SENSOR_IN_SOFTIRQ_CONTEXT)) {
|
|
struct is_group *child_group
|
|
= GET_HEAD_GROUP_IN_DEVICE(IS_DEVICE_ISCHAIN, group);
|
|
|
|
if (sensor->ischain && child_group)
|
|
tasklet_kill(&devicemgr->tasklet[group->instance]);
|
|
}
|
|
|
|
if (!test_bit(IS_SENSOR_ONLY, &sensor->state) && sensor->ischain) {
|
|
ret = is_ischain_stop_wrap(sensor->ischain, group);
|
|
if (ret) {
|
|
merr("is_ischain_stop_wrap is fail(%d)", sensor->ischain, ret);
|
|
ret = -EINVAL;
|
|
goto p_err;
|
|
}
|
|
} else {
|
|
ret = is_groupmgr_stop(sensor->groupmgr, group->device);
|
|
if (ret) {
|
|
merr("is_groupmgr_stop is fail(%d)", group->device, ret);
|
|
ret = -EINVAL;
|
|
goto p_err;
|
|
}
|
|
}
|
|
break;
|
|
case IS_DEVICE_ISCHAIN:
|
|
break;
|
|
default:
|
|
err("device type(%d) is invalid", type);
|
|
BUG();
|
|
break;
|
|
}
|
|
|
|
p_err:
|
|
return ret;
|
|
}
|
|
|
|
int is_devicemgr_close(struct is_devicemgr *devicemgr,
|
|
void *device, enum is_device_type type)
|
|
{
|
|
int ret = 0;
|
|
struct is_group *group;
|
|
struct is_device_sensor *sensor;
|
|
|
|
switch (type) {
|
|
case IS_DEVICE_SENSOR:
|
|
sensor = (struct is_device_sensor *)device;
|
|
|
|
FIMC_BUG(!sensor);
|
|
|
|
group = &sensor->group_sensor;
|
|
|
|
ret = is_group_close(sensor->groupmgr, group);
|
|
if (ret)
|
|
merr("is_group_close is fail", sensor);
|
|
|
|
/*
|
|
* Forcely set the ischain's state to "Not Opened"
|
|
* Because if it's sensor driving mode, ischain was not opened from HAL.
|
|
*/
|
|
if (test_bit(IS_SENSOR_ONLY, &sensor->state) && sensor->ischain)
|
|
clear_bit(IS_ISCHAIN_OPEN, &sensor->ischain->state);
|
|
break;
|
|
case IS_DEVICE_ISCHAIN:
|
|
break;
|
|
default:
|
|
err("device type(%d) is invalid", type);
|
|
BUG();
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int __nocfi is_devicemgr_shot_prepare(struct is_group *group,
|
|
struct is_frame *frame,
|
|
u32 fcount,
|
|
enum is_device_type type)
|
|
{
|
|
struct is_device_ischain *idi = group->device;
|
|
struct pablo_rta_frame_info *prfi;
|
|
struct is_framemgr *framemgr;
|
|
struct is_frame *ldr_frame;
|
|
|
|
if (IS_ENABLED(IMAGE_RTA) && group->id == GROUP_ID_BYRP) {
|
|
framemgr = GET_HEAD_GROUP_FRAMEMGR(group, frame->cur_shot_idx);
|
|
if (!framemgr) {
|
|
mgerr("framemgr is NULL", idi, group);
|
|
return 0;
|
|
}
|
|
|
|
ldr_frame = find_frame(framemgr, FS_PROCESS, frame_fcount,
|
|
(void *)(ulong)frame->fcount);
|
|
if (!ldr_frame) {
|
|
ldr_frame = find_frame(framemgr, FS_STRIPE_PROCESS,
|
|
frame_fcount,
|
|
(void *)(ulong)frame->fcount);
|
|
}
|
|
|
|
if (!ldr_frame) {
|
|
mgerr("failed to get leader frame", idi, group);
|
|
return 0;
|
|
}
|
|
|
|
prfi = &ldr_frame->prfi;
|
|
if (test_bit(IS_ISCHAIN_REPROCESSING, &idi->state)) {
|
|
mgrdbgs(1, "set_frame_info\n", idi, group, ldr_frame);
|
|
|
|
((set_frame_info_func_t)SET_FRAME_INFO_FUNC_ADDR)(
|
|
idi->instance, ldr_frame->fcount, (void *)&ldr_frame->prfi);
|
|
}
|
|
|
|
mgrdbgs(1, "trigger_image_rta\n", idi, group, ldr_frame);
|
|
|
|
((trigger_image_rta_func_t)TRIGGER_IMAGE_RTA_FUNC_ADDR)(
|
|
idi->instance, ldr_frame->fcount, (void *)&ldr_frame->prfi);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int __nocfi is_devicemgr_shot_callback(struct is_group *group,
|
|
struct is_frame *frame,
|
|
u32 fcount,
|
|
enum is_device_type type)
|
|
{
|
|
int ret = 0;
|
|
unsigned long flags;
|
|
struct is_group *child_group;
|
|
struct camera2_node ldr_node = {0, };
|
|
struct is_devicemgr *devicemgr;
|
|
struct devicemgr_sensor_tag_data *tag_data;
|
|
u32 stream;
|
|
int vc;
|
|
struct is_subdev *subdev;
|
|
struct is_device_sensor *sensor;
|
|
|
|
switch (type) {
|
|
case IS_DEVICE_SENSOR:
|
|
if (IS_ENABLED(IMAGE_RTA) &&
|
|
(group->id >= GROUP_ID_SS0 && group->id <= GROUP_ID_SS5)) {
|
|
struct is_device_ischain *idi = group->device;
|
|
|
|
mgrdbgs(1, "set_frame_info\n", idi, group, frame);
|
|
|
|
((set_frame_info_func_t)SET_FRAME_INFO_FUNC_ADDR)(
|
|
idi->instance, frame->fcount, (void *)&idi->prfi);
|
|
}
|
|
|
|
child_group = GET_HEAD_GROUP_IN_DEVICE(IS_DEVICE_ISCHAIN, group);
|
|
|
|
PROGRAM_COUNT(9);
|
|
|
|
mgrdbgs(1, " DEVICE SHOT CALLBACK(%d) %s\n", group->device,
|
|
group, frame, frame->index, child_group ? "OTF" : "M2M");
|
|
|
|
/* OTF */
|
|
/* IS_SENSOR_OTF_OUTPUT bit needs to check also.
|
|
* because this bit can be cleared for not operate child_group_shot at remosaic sensor mode
|
|
*/
|
|
if (child_group && test_bit(IS_SENSOR_OTF_OUTPUT, &group->device->sensor->state)) {
|
|
ret = child_group->shot_callback(child_group->device, child_group, frame);
|
|
if (ret) {
|
|
mgerr("child_group->shot_callback(%d)", child_group, child_group, ret);
|
|
goto p_err;
|
|
}
|
|
/* M2M */
|
|
} else {
|
|
ret = is_sensor_group_tag(group->device->sensor, frame, &ldr_node);
|
|
if (ret) {
|
|
merr("is_sensor_group_tag is fail(%d)", group, ret);
|
|
mginfo("[F%d] Start CANCEL Other subdev frame\n", group->device, group, frame->fcount);
|
|
flags = is_group_lock(group, group->device_type, true);
|
|
is_group_subdev_cancel(group, frame, group->device_type, FS_PROCESS, true);
|
|
is_group_subdev_cancel(group, frame, group->device_type, FS_REQUEST, false);
|
|
is_group_unlock(group, flags, group->device_type, true);
|
|
mginfo("[F%d] End CANCEL Other subdev frame\n", group->device, group, frame->fcount);
|
|
ret = -EINVAL;
|
|
goto p_err;
|
|
}
|
|
#if defined(USE_OFFLINE_PROCESSING)
|
|
ret = is_ischain_update_sensor_mode(group->device, frame);
|
|
if (ret) {
|
|
merr("is_ischain_update_sensor_mode is fail(%d)", group->device, ret);
|
|
goto p_err;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
PROGRAM_COUNT(10);
|
|
|
|
break;
|
|
case IS_DEVICE_ISCHAIN:
|
|
sensor = group->head->sensor;
|
|
|
|
for (vc = ENTRY_SSVC0; vc <= ENTRY_SSVC3; vc++) {
|
|
subdev = group->head->subdev[vc];
|
|
if (subdev && test_bit(IS_SUBDEV_VOTF_USE, &subdev->state)) {
|
|
ret = is_sensor_votf_tag(sensor, subdev);
|
|
if (ret)
|
|
msrwarn("votf_frame is drop(%d)", sensor, subdev, frame, ret);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Sensor Tag Pre-conditions
|
|
* 1. Current shot is EXTERNAL with single buffer.
|
|
* 2. Current shot is MULTI,
|
|
* but it's the first buffer of batch buffer.
|
|
*/
|
|
if (frame->cur_buf_index > 0
|
|
|| (frame->type != SHOT_TYPE_EXTERNAL
|
|
&& frame->type != SHOT_TYPE_MULTI))
|
|
break;
|
|
|
|
devicemgr = group->device->devicemgr;
|
|
stream = sensor->instance;
|
|
|
|
tag_data = &devicemgr->tag_data[stream];
|
|
tag_data->fcount = fcount;
|
|
tag_data->devicemgr = devicemgr;
|
|
tag_data->group = &devicemgr->sensor[stream]->group_sensor;
|
|
tag_data->stream = stream;
|
|
tag_data->cur_shot_idx = frame->cur_shot_idx;
|
|
|
|
if (IS_ENABLED(CHAIN_TAG_SENSOR_IN_SOFTIRQ_CONTEXT)) {
|
|
mgrdbgs(1, "schedule sensor tag tasklet\n", group->device, group, frame);
|
|
tasklet_schedule(&devicemgr->tasklet[stream]);
|
|
} else { /* (hard)IRQ context */
|
|
do_sensor_tag((unsigned long)tag_data);
|
|
}
|
|
|
|
break;
|
|
default:
|
|
mgerr("device type(%d) is invalid", group, group, group->device_type);
|
|
BUG();
|
|
break;
|
|
}
|
|
|
|
p_err:
|
|
return ret;
|
|
}
|
|
|
|
int is_devicemgr_shot_done(struct is_group *group,
|
|
struct is_frame *ldr_frame,
|
|
u32 status)
|
|
{
|
|
int ret = 0;
|
|
unsigned long flags;
|
|
|
|
/* skip in case of the sensor -> 3AA M2M case */
|
|
if (group->device_type == IS_DEVICE_ISCHAIN)
|
|
return ret;
|
|
|
|
/*
|
|
* When error happens, cancel the sensor's subdev frames
|
|
* - CONFIG_LOCK_DELAY: Skip cancel because the sensor subdev has already finished its processing.
|
|
* - LATE_FRAME: FS_REQUEST frame is handled by 'is_devicemgr_late_shot_handle()'.
|
|
*/
|
|
if (status == IS_SHOT_LATE_FRAME) {
|
|
mginfo("[F%d] Start CANCEL Other subdev frame\n", group->device, group, ldr_frame->fcount);
|
|
flags = is_group_lock(group, group->device_type, false);
|
|
is_group_subdev_cancel(group, ldr_frame, group->device_type, FS_PROCESS, true);
|
|
is_group_unlock(group, flags, group->device_type, false);
|
|
mginfo("[F%d] End CANCEL Other subdev frame\n", group->device, group, ldr_frame->fcount);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void is_devicemgr_late_shot_handle(struct is_group *group, struct is_frame *frame, u32 status)
|
|
{
|
|
unsigned long flags;
|
|
struct is_framemgr *framemgr;
|
|
unsigned long framemgr_flag;
|
|
struct is_frame *ldr_frame;
|
|
|
|
info("%s: fcount(%d)", __func__, frame->fcount);
|
|
|
|
if (group->device_type == IS_DEVICE_ISCHAIN)
|
|
return;
|
|
|
|
framemgr = GET_HEAD_GROUP_FRAMEMGR(group, frame->cur_shot_idx);
|
|
if (!framemgr) {
|
|
merr("framemgr is NULL", group);
|
|
return;
|
|
}
|
|
|
|
framemgr_e_barrier_irqs(framemgr, 0, framemgr_flag);
|
|
ldr_frame = find_frame(framemgr, FS_PROCESS, frame_fcount, (void *)(ulong)frame->fcount);
|
|
|
|
if (!ldr_frame) {
|
|
frame_manager_print_queues(framemgr);
|
|
merr("[F%d] There's no frame in processing." \
|
|
"Can't sync sensor and ischain buffer anymore..",
|
|
group, frame->fcount);
|
|
framemgr_x_barrier_irqr(framemgr, 0, framemgr_flag);
|
|
return;
|
|
}
|
|
framemgr_x_barrier_irqr(framemgr, 0, framemgr_flag);
|
|
|
|
/* if error happened, cancel the sensor's subdev frames */
|
|
if (status) {
|
|
mginfo("[F%d] Start CANCEL Other subdev frame\n", group->device, group, ldr_frame->fcount);
|
|
flags = is_group_lock(group, group->device_type, false);
|
|
is_group_subdev_cancel(group, ldr_frame, group->device_type, FS_REQUEST, false);
|
|
is_group_unlock(group, flags, group->device_type, false);
|
|
mginfo("[F%d] End CANCEL Other subdev frame\n", group->device, group, ldr_frame->fcount);
|
|
}
|
|
|
|
return;
|
|
}
|
|
#else
|
|
struct is_group *get_ischain_leader_group(struct is_device_ischain *device)
|
|
{
|
|
return device->groupmgr->leader[device->instance];
|
|
}
|
|
|
|
int is_devicemgr_probe(struct is_devicemgr *devicemgr)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int is_devicemgr_open(struct is_devicemgr *devicemgr,
|
|
void *device, enum is_device_type type)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int is_devicemgr_binding(struct is_devicemgr *devicemgr,
|
|
struct is_device_sensor *sensor,
|
|
struct is_device_ischain *ischain,
|
|
enum is_device_type type)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int is_devicemgr_start(struct is_devicemgr *devicemgr,
|
|
void *device, enum is_device_type type)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int is_devicemgr_stop(struct is_devicemgr *devicemgr,
|
|
void *device, enum is_device_type type)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int is_devicemgr_close(struct is_devicemgr *devicemgr,
|
|
void *device, enum is_device_type type)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int is_devicemgr_shot_prepare(struct is_group *group,
|
|
struct is_frame *frame,
|
|
u32 fcount,
|
|
enum is_device_type type)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int is_devicemgr_shot_callback(struct is_group *group,
|
|
struct is_frame *frame,
|
|
u32 fcount,
|
|
enum is_device_type type)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int is_devicemgr_shot_done(struct is_group *group,
|
|
struct is_frame *ldr_frame,
|
|
u32 status)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|