Add sync file op support in VI driver.
Sub devices will be synchronized when the MFI interrupt
arrives to VI driver. At present this interrupt is
configured when the ROI of focus area ends during the
current frame capture.
Fix vi2 and vi4 differences using fops in addition to
the original commit.
Cleanup MFI code in the active isr flow.
Bug
1754305
Change-Id: I7e96d413e79dbab17c7c4349cef9ef6b78ab983d
Signed-off-by: Bhanu Murthy V <bmurthyv@nvidia.com>
Reviewed-on: http://git-master/r/
1162764
(cherry picked from commit
8c7c212927f1b1703fe0bf95086605fef48ff89d)
Reviewed-on: http://git-master/r/
1327223
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
}
}
+int tegra_vi_mfi_work(struct tegra_mc_vi *vi, int channel)
+{
+ if (vi->fops)
+ return vi->fops->vi_mfi_work(vi, channel);
+
+ return 0;
+}
+EXPORT_SYMBOL(tegra_vi_mfi_work);
+
int tegra_vi_channels_init(struct tegra_mc_vi *vi)
{
int ret = 0;
#include "host1x/host1x.h"
#include "camera/vi/registers.h"
+static struct tegra_mc_vi *tegra_mcvi;
+
+struct tegra_mc_vi *tegra_get_mc_vi(void)
+{
+ return tegra_mcvi;
+}
+EXPORT_SYMBOL(tegra_get_mc_vi);
+
/* In TPG mode, VI only support 2 formats */
static void vi_tpg_fmts_bitmap_init(struct tegra_channel *chan)
{
if (err < 0)
goto register_error;
+ tegra_mcvi = mc_vi;
+
return 0;
register_error:
tegra_vi_graph_cleanup(mc_vi);
tegra_vi_channels_cleanup(mc_vi);
tegra_vi_v4l2_cleanup(mc_vi);
+ tegra_mcvi = NULL;
}
EXPORT_SYMBOL(tegra_vi_media_controller_cleanup);
void tegra_channel_ec_close(struct tegra_mc_vi *mc_vi);
void tegra_channel_query_hdmiin_unplug(struct tegra_channel *chan,
struct v4l2_event *event);
+int tegra_vi_mfi_work(struct tegra_mc_vi *mc_vi, int csiport);
int tpg_vi_media_controller_init(struct tegra_mc_vi *mc_vi, int pg_mode);
void tpg_vi_media_controller_cleanup(struct tegra_mc_vi *mc_vi);
+struct tegra_mc_vi *tegra_get_mc_vi(void);
u32 tegra_core_get_fourcc_by_idx(struct tegra_channel *chan,
unsigned int index);
int (*vi_stop_streaming)(struct vb2_queue *vq);
int (*vi_add_ctrls)(struct tegra_channel *chan);
void (*vi_init_video_formats)(struct tegra_channel *chan);
+ int (*vi_mfi_work)(struct tegra_mc_vi *vi, int port);
};
struct tegra_csi_fops {
vi_channel_syncpt_free(chan);
}
+int vi2_mfi_work(struct tegra_mc_vi *vi, int csiport)
+{
+ struct tegra_channel *it;
+ int ret = 0;
+
+ /* for vi2, the input argument is the actual CSI port itself */
+ /* search the list and match the port */
+ list_for_each_entry(it, &vi->vi_chans, list) {
+ if (csiport == it->port[0]) {
+ ret = v4l2_subdev_call(it->subdev_on_csi, core,
+ sync, V4L2_SYNC_EVENT_FOCUS_POS);
+ if (ret < 0 && ret != -ENOIOCTLCMD) {
+ dev_err(vi->dev,
+ "%s:channel failed\n", __func__);
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+}
+
int tegra_vi2_power_on(struct tegra_mc_vi *vi)
{
int ret;
int vi2_channel_stop_streaming(struct vb2_queue *vq);
int vi2_add_ctrls(struct tegra_channel *chan);
void vi2_init_video_formats(struct tegra_channel *chan);
+int vi2_mfi_work(struct tegra_mc_vi *vi, int csiport);
struct tegra_vi_fops vi2_fops = {
.vi_power_on = vi2_power_on,
.vi_stop_streaming = vi2_channel_stop_streaming,
.vi_add_ctrls = vi2_add_ctrls,
.vi_init_video_formats = vi2_init_video_formats,
+ .vi_mfi_work = vi2_mfi_work,
};
#endif
return 0;
}
+int vi4_mfi_work(struct tegra_mc_vi *vi, int channel)
+{
+ struct tegra_channel *it = NULL;
+ int ret = 0;
+
+ /* for vi4, the input argument is the hw channel id*/
+ /* search the list and match the hw id */
+ list_for_each_entry(it, &vi->vi_chans, list) {
+ if (channel == it->vnc_id[0]) {
+ ret = v4l2_subdev_call(it->subdev_on_csi, core,
+ sync, V4L2_SYNC_EVENT_FOCUS_POS);
+ if (ret < 0 && ret != -ENOIOCTLCMD) {
+ dev_err(vi->dev,
+ "%s:channel failed\n", __func__);
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+}
+
int tegra_vi4_power_on(struct tegra_mc_vi *vi)
{
int ret;
int vi4_channel_stop_streaming(struct vb2_queue *vq);
int vi4_add_ctrls(struct tegra_channel *chan);
void vi4_init_video_formats(struct tegra_channel *chan);
+int vi4_mfi_work(struct tegra_mc_vi *vi, int channel);
struct tegra_vi_fops vi4_fops = {
.vi_power_on = vi4_power_on,
.vi_stop_streaming = vi4_channel_stop_streaming,
.vi_add_ctrls = vi4_add_ctrls,
.vi_init_video_formats = vi4_init_video_formats,
+ .vi_mfi_work = vi4_mfi_work,
};
#endif
struct work_struct mfi_cb_work;
struct rcu_head rcu;
u8 channel;
+ void *priv;
};
struct tegra_vi_mfi_ctx {
{
struct tegra_mfi_chan *mfi_chan =
container_of(vi_work, struct tegra_mfi_chan, mfi_cb_work);
+ struct tegra_mc_vi *vi = tegra_get_mc_vi();
mutex_lock(&vi_isr_lock);
- if (mfi_callback == NULL) {
- pr_debug("NULL callback\n");
- mutex_unlock(&vi_isr_lock);
- return;
- }
- if (mfi_callback_arg)
- mfi_callback_arg->vi_chan = mfi_chan->channel;
- mfi_callback(mfi_callback_arg);
+ tegra_vi_mfi_work(vi, mfi_chan->channel);
mutex_unlock(&vi_isr_lock);
}