Commit 633b388f authored by Robert Foss's avatar Robert Foss Committed by Mauro Carvalho Chehab

media: camss: Refactor VFE HW version support

In order to support Qualcomm ISP hardware architectures that diverge
from older architectures, the VFE subdevice driver needs to be refactored
to better abstract the different ISP architectures.

Gen1 represents the CAMSS ISP architecture. The ISP architecture developed
after CAMSS, Titan, will be referred to as Gen2.
Signed-off-by: default avatarRobert Foss <robert.foss@linaro.org>
Reviewed-by: default avatarAndrey Konovalov <andrey.konovalov@linaro.org>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 9d95baf9
......@@ -10,6 +10,8 @@ qcom-camss-objs += \
camss-ispif.o \
camss-vfe-4-1.o \
camss-vfe-4-7.o \
camss-vfe-4-8.o \
camss-vfe-gen1.o \
camss-vfe.o \
camss-video.o \
......
......@@ -14,6 +14,7 @@
#include "camss.h"
#include "camss-vfe.h"
#include "camss-vfe-gen1.h"
#define VFE_0_HW_VERSION 0x000
......@@ -284,30 +285,6 @@ static void vfe_wm_frame_based(struct vfe_device *vfe, u8 wm, u8 enable)
1 << VFE_0_BUS_IMAGE_MASTER_n_WR_CFG_FRM_BASED_SHIFT);
}
#define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N))
static int vfe_word_per_line(u32 format, u32 pixel_per_line)
{
int val = 0;
switch (format) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_NV61:
val = CALC_WORD(pixel_per_line, 1, 8);
break;
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
case V4L2_PIX_FMT_UYVY:
case V4L2_PIX_FMT_VYUY:
val = CALC_WORD(pixel_per_line, 2, 8);
break;
}
return val;
}
static void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane,
u16 *width, u16 *height, u16 *bytesperline)
{
......@@ -666,20 +643,6 @@ static void vfe_set_demux_cfg(struct vfe_device *vfe, struct vfe_line *line)
writel_relaxed(odd_cfg, vfe->base + VFE_0_DEMUX_ODD_CFG);
}
static inline u8 vfe_calc_interp_reso(u16 input, u16 output)
{
if (input / output >= 16)
return 0;
if (input / output >= 8)
return 1;
if (input / output >= 4)
return 2;
return 3;
}
static void vfe_set_scale_cfg(struct vfe_device *vfe, struct vfe_line *line)
{
u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
......@@ -975,46 +938,62 @@ static irqreturn_t vfe_isr(int irq, void *dev)
return IRQ_HANDLED;
}
const struct vfe_hw_ops vfe_ops_4_1 = {
.hw_version_read = vfe_hw_version_read,
static const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_1 = {
.bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi,
.bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi,
.bus_enable_wr_if = vfe_bus_enable_wr_if,
.bus_reload_wm = vfe_bus_reload_wm,
.camif_wait_for_stop = vfe_camif_wait_for_stop,
.enable_irq_common = vfe_enable_irq_common,
.enable_irq_pix_line = vfe_enable_irq_pix_line,
.enable_irq_wm_line = vfe_enable_irq_wm_line,
.get_ub_size = vfe_get_ub_size,
.global_reset = vfe_global_reset,
.halt_request = vfe_halt_request,
.halt_clear = vfe_halt_clear,
.halt_request = vfe_halt_request,
.set_camif_cfg = vfe_set_camif_cfg,
.set_camif_cmd = vfe_set_camif_cmd,
.set_cgc_override = vfe_set_cgc_override,
.set_clamp_cfg = vfe_set_clamp_cfg,
.set_crop_cfg = vfe_set_crop_cfg,
.set_demux_cfg = vfe_set_demux_cfg,
.set_ds = vfe_set_ds,
.set_module_cfg = vfe_set_module_cfg,
.set_qos = vfe_set_qos,
.set_rdi_cid = vfe_set_rdi_cid,
.set_realign_cfg = vfe_set_realign_cfg,
.set_scale_cfg = vfe_set_scale_cfg,
.set_xbar_cfg = vfe_set_xbar_cfg,
.wm_enable = vfe_wm_enable,
.wm_frame_based = vfe_wm_frame_based,
.wm_get_ping_pong_status = vfe_wm_get_ping_pong_status,
.wm_line_based = vfe_wm_line_based,
.wm_set_framedrop_period = vfe_wm_set_framedrop_period,
.wm_set_framedrop_pattern = vfe_wm_set_framedrop_pattern,
.wm_set_ub_cfg = vfe_wm_set_ub_cfg,
.bus_reload_wm = vfe_bus_reload_wm,
.wm_set_framedrop_period = vfe_wm_set_framedrop_period,
.wm_set_ping_addr = vfe_wm_set_ping_addr,
.wm_set_pong_addr = vfe_wm_set_pong_addr,
.wm_get_ping_pong_status = vfe_wm_get_ping_pong_status,
.bus_enable_wr_if = vfe_bus_enable_wr_if,
.bus_connect_wm_to_rdi = vfe_bus_connect_wm_to_rdi,
.wm_set_subsample = vfe_wm_set_subsample,
.bus_disconnect_wm_from_rdi = vfe_bus_disconnect_wm_from_rdi,
.set_xbar_cfg = vfe_set_xbar_cfg,
.set_realign_cfg = vfe_set_realign_cfg,
.set_rdi_cid = vfe_set_rdi_cid,
.reg_update = vfe_reg_update,
.reg_update_clear = vfe_reg_update_clear,
.enable_irq_wm_line = vfe_enable_irq_wm_line,
.enable_irq_pix_line = vfe_enable_irq_pix_line,
.enable_irq_common = vfe_enable_irq_common,
.set_demux_cfg = vfe_set_demux_cfg,
.set_scale_cfg = vfe_set_scale_cfg,
.set_crop_cfg = vfe_set_crop_cfg,
.set_clamp_cfg = vfe_set_clamp_cfg,
.set_qos = vfe_set_qos,
.set_ds = vfe_set_ds,
.set_cgc_override = vfe_set_cgc_override,
.set_camif_cfg = vfe_set_camif_cfg,
.set_camif_cmd = vfe_set_camif_cmd,
.set_module_cfg = vfe_set_module_cfg,
.camif_wait_for_stop = vfe_camif_wait_for_stop,
.wm_set_ub_cfg = vfe_wm_set_ub_cfg,
};
static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe)
{
vfe->isr_ops = vfe_isr_ops_gen1;
vfe->ops_gen1 = &vfe_ops_gen1_4_1;
vfe->video_ops = vfe_video_ops_gen1;
vfe->line_num = VFE_LINE_NUM_GEN1;
}
const struct vfe_hw_ops vfe_ops_4_1 = {
.global_reset = vfe_global_reset,
.hw_version_read = vfe_hw_version_read,
.isr_read = vfe_isr_read,
.violation_read = vfe_violation_read,
.isr = vfe_isr,
.reg_update_clear = vfe_reg_update_clear,
.reg_update = vfe_reg_update,
.subdev_init = vfe_subdev_init,
.vfe_disable = vfe_gen1_disable,
.vfe_enable = vfe_gen1_enable,
.vfe_halt = vfe_gen1_halt,
.violation_read = vfe_violation_read,
};
This diff is collapsed.
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/*
* camss-vfe.h
*
* Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module
*
* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
* Copyright (C) 2015-2018 Linaro Ltd.
*/
#ifndef QC_MSM_CAMSS_VFE_GEN1_H
#define QC_MSM_CAMSS_VFE_GEN1_H
#include "camss-vfe.h"
enum vfe_line_id;
struct vfe_device;
struct vfe_line;
struct vfe_output;
struct vfe_hw_ops_gen1 {
void (*bus_connect_wm_to_rdi)(struct vfe_device *vfe, u8 wm, enum vfe_line_id id);
void (*bus_disconnect_wm_from_rdi)(struct vfe_device *vfe, u8 wm, enum vfe_line_id id);
void (*bus_enable_wr_if)(struct vfe_device *vfe, u8 enable);
void (*bus_reload_wm)(struct vfe_device *vfe, u8 wm);
int (*camif_wait_for_stop)(struct vfe_device *vfe, struct device *dev);
void (*enable_irq_common)(struct vfe_device *vfe);
void (*enable_irq_wm_line)(struct vfe_device *vfe, u8 wm, enum vfe_line_id line_id,
u8 enable);
void (*enable_irq_pix_line)(struct vfe_device *vfe, u8 comp, enum vfe_line_id line_id,
u8 enable);
u16 (*get_ub_size)(u8 vfe_id);
void (*halt_clear)(struct vfe_device *vfe);
void (*halt_request)(struct vfe_device *vfe);
void (*set_camif_cfg)(struct vfe_device *vfe, struct vfe_line *line);
void (*set_camif_cmd)(struct vfe_device *vfe, u8 enable);
void (*set_cgc_override)(struct vfe_device *vfe, u8 wm, u8 enable);
void (*set_clamp_cfg)(struct vfe_device *vfe);
void (*set_crop_cfg)(struct vfe_device *vfe, struct vfe_line *line);
void (*set_demux_cfg)(struct vfe_device *vfe, struct vfe_line *line);
void (*set_ds)(struct vfe_device *vfe);
void (*set_module_cfg)(struct vfe_device *vfe, u8 enable);
void (*set_scale_cfg)(struct vfe_device *vfe, struct vfe_line *line);
void (*set_rdi_cid)(struct vfe_device *vfe, enum vfe_line_id id, u8 cid);
void (*set_realign_cfg)(struct vfe_device *vfe, struct vfe_line *line, u8 enable);
void (*set_qos)(struct vfe_device *vfe);
void (*set_xbar_cfg)(struct vfe_device *vfe, struct vfe_output *output, u8 enable);
void (*wm_frame_based)(struct vfe_device *vfe, u8 wm, u8 enable);
void (*wm_line_based)(struct vfe_device *vfe, u32 wm, struct v4l2_pix_format_mplane *pix,
u8 plane, u32 enable);
void (*wm_set_ub_cfg)(struct vfe_device *vfe, u8 wm, u16 offset, u16 depth);
void (*wm_set_subsample)(struct vfe_device *vfe, u8 wm);
void (*wm_set_framedrop_period)(struct vfe_device *vfe, u8 wm, u8 per);
void (*wm_set_framedrop_pattern)(struct vfe_device *vfe, u8 wm, u32 pattern);
void (*wm_set_ping_addr)(struct vfe_device *vfe, u8 wm, u32 addr);
void (*wm_set_pong_addr)(struct vfe_device *vfe, u8 wm, u32 addr);
int (*wm_get_ping_pong_status)(struct vfe_device *vfe, u8 wm);
void (*wm_enable)(struct vfe_device *vfe, u8 wm, u8 enable);
};
/*
* vfe_calc_interp_reso - Calculate interpolation mode
* @input: Input resolution
* @output: Output resolution
*
* Return interpolation mode
*/
static inline u8 vfe_calc_interp_reso(u16 input, u16 output)
{
if (input / output >= 16)
return 0;
if (input / output >= 8)
return 1;
if (input / output >= 4)
return 2;
return 3;
}
/*
* vfe_gen1_disable - Disable streaming on VFE line
* @line: VFE line
*
* Return 0 on success or a negative error code otherwise
*/
int vfe_gen1_disable(struct vfe_line *line);
/*
* vfe_gen1_enable - Enable VFE module
* @line: VFE line
*
* Return 0 on success
*/
int vfe_gen1_enable(struct vfe_line *line);
/*
* vfe_gen1_enable - Halt VFE module
* @vfe: VFE device
*
* Return 0 on success
*/
int vfe_gen1_halt(struct vfe_device *vfe);
/*
* vfe_word_per_line - Calculate number of words per frame width
* @format: V4L2 format
* @width: Frame width
*
* Return number of words per frame width
*/
int vfe_word_per_line(u32 format, u32 width);
extern const struct vfe_isr_ops vfe_isr_ops_gen1;
extern const struct camss_video_ops vfe_video_ops_gen1;
#endif /* QC_MSM_CAMSS_VFE_GEN1_H */
......@@ -17,15 +17,26 @@
#include <media/v4l2-subdev.h>
#include "camss-video.h"
#include "camss-vfe-gen1.h"
#define MSM_VFE_PAD_SINK 0
#define MSM_VFE_PAD_SRC 1
#define MSM_VFE_PADS_NUM 2
#define MSM_VFE_LINE_NUM 4
#define MSM_VFE_IMAGE_MASTERS_NUM 7
#define MSM_VFE_COMPOSITE_IRQ_NUM 4
/* VFE halt timeout */
#define VFE_HALT_TIMEOUT_MS 100
/* Frame drop value. VAL + UPDATES - 1 should not exceed 31 */
#define VFE_FRAME_DROP_VAL 30
#define vfe_line_array(ptr_line) \
((const struct vfe_line (*)[]) &(ptr_line)[-(ptr_line)->id])
#define to_vfe(ptr_line) \
container_of(vfe_line_array(ptr_line), struct vfe_device, line)
enum vfe_output_state {
VFE_OUTPUT_OFF,
VFE_OUTPUT_RESERVED,
......@@ -40,23 +51,30 @@ enum vfe_line_id {
VFE_LINE_RDI0 = 0,
VFE_LINE_RDI1 = 1,
VFE_LINE_RDI2 = 2,
VFE_LINE_PIX = 3
VFE_LINE_PIX = 3,
VFE_LINE_NUM_GEN1 = 4,
VFE_LINE_NUM_MAX = 4
};
struct vfe_output {
u8 wm_num;
u8 wm_idx[3];
int active_buf;
struct camss_buffer *buf[2];
struct camss_buffer *last_buffer;
struct list_head pending_bufs;
unsigned int drop_update_idx;
union {
struct {
int active_buf;
int wait_sof;
} gen1;
};
enum vfe_output_state state;
unsigned int sequence;
int wait_sof;
int wait_reg_update;
struct completion sof;
struct completion reg_update;
......@@ -78,59 +96,19 @@ struct vfe_line {
struct vfe_device;
struct vfe_hw_ops {
void (*hw_version_read)(struct vfe_device *vfe, struct device *dev);
u16 (*get_ub_size)(u8 vfe_id);
void (*enable_irq_common)(struct vfe_device *vfe);
void (*global_reset)(struct vfe_device *vfe);
void (*halt_request)(struct vfe_device *vfe);
void (*halt_clear)(struct vfe_device *vfe);
void (*wm_enable)(struct vfe_device *vfe, u8 wm, u8 enable);
void (*wm_frame_based)(struct vfe_device *vfe, u8 wm, u8 enable);
void (*wm_line_based)(struct vfe_device *vfe, u32 wm,
struct v4l2_pix_format_mplane *pix,
u8 plane, u32 enable);
void (*wm_set_framedrop_period)(struct vfe_device *vfe, u8 wm, u8 per);
void (*wm_set_framedrop_pattern)(struct vfe_device *vfe, u8 wm,
u32 pattern);
void (*wm_set_ub_cfg)(struct vfe_device *vfe, u8 wm, u16 offset,
u16 depth);
void (*bus_reload_wm)(struct vfe_device *vfe, u8 wm);
void (*wm_set_ping_addr)(struct vfe_device *vfe, u8 wm, u32 addr);
void (*wm_set_pong_addr)(struct vfe_device *vfe, u8 wm, u32 addr);
int (*wm_get_ping_pong_status)(struct vfe_device *vfe, u8 wm);
void (*bus_enable_wr_if)(struct vfe_device *vfe, u8 enable);
void (*bus_connect_wm_to_rdi)(struct vfe_device *vfe, u8 wm,
enum vfe_line_id id);
void (*wm_set_subsample)(struct vfe_device *vfe, u8 wm);
void (*bus_disconnect_wm_from_rdi)(struct vfe_device *vfe, u8 wm,
enum vfe_line_id id);
void (*set_xbar_cfg)(struct vfe_device *vfe, struct vfe_output *output,
u8 enable);
void (*set_rdi_cid)(struct vfe_device *vfe, enum vfe_line_id id,
u8 cid);
void (*set_realign_cfg)(struct vfe_device *vfe, struct vfe_line *line,
u8 enable);
void (*hw_version_read)(struct vfe_device *vfe, struct device *dev);
irqreturn_t (*isr)(int irq, void *dev);
void (*isr_read)(struct vfe_device *vfe, u32 *value0, u32 *value1);
void (*reg_update)(struct vfe_device *vfe, enum vfe_line_id line_id);
void (*reg_update_clear)(struct vfe_device *vfe,
enum vfe_line_id line_id);
void (*enable_irq_wm_line)(struct vfe_device *vfe, u8 wm,
enum vfe_line_id line_id, u8 enable);
void (*enable_irq_pix_line)(struct vfe_device *vfe, u8 comp,
enum vfe_line_id line_id, u8 enable);
void (*enable_irq_common)(struct vfe_device *vfe);
void (*set_demux_cfg)(struct vfe_device *vfe, struct vfe_line *line);
void (*set_scale_cfg)(struct vfe_device *vfe, struct vfe_line *line);
void (*set_crop_cfg)(struct vfe_device *vfe, struct vfe_line *line);
void (*set_clamp_cfg)(struct vfe_device *vfe);
void (*set_qos)(struct vfe_device *vfe);
void (*set_ds)(struct vfe_device *vfe);
void (*set_cgc_override)(struct vfe_device *vfe, u8 wm, u8 enable);
void (*set_camif_cfg)(struct vfe_device *vfe, struct vfe_line *line);
void (*set_camif_cmd)(struct vfe_device *vfe, u8 enable);
void (*set_module_cfg)(struct vfe_device *vfe, u8 enable);
int (*camif_wait_for_stop)(struct vfe_device *vfe, struct device *dev);
void (*isr_read)(struct vfe_device *vfe, u32 *value0, u32 *value1);
void (*subdev_init)(struct device *dev, struct vfe_device *vfe);
int (*vfe_disable)(struct vfe_line *line);
int (*vfe_enable)(struct vfe_line *line);
int (*vfe_halt)(struct vfe_device *vfe);
void (*violation_read)(struct vfe_device *vfe);
irqreturn_t (*isr)(int irq, void *dev);
};
struct vfe_isr_ops {
......@@ -158,11 +136,14 @@ struct vfe_device {
int stream_count;
spinlock_t output_lock;
enum vfe_line_id wm_output_map[MSM_VFE_IMAGE_MASTERS_NUM];
struct vfe_line line[MSM_VFE_LINE_NUM];
struct vfe_line line[VFE_LINE_NUM_MAX];
u8 line_num;
u32 reg_update;
u8 was_streaming;
const struct vfe_hw_ops *ops;
const struct vfe_hw_ops_gen1 *ops_gen1;
struct vfe_isr_ops isr_ops;
struct camss_video_ops video_ops;
};
struct resources;
......@@ -178,6 +159,37 @@ void msm_vfe_unregister_entities(struct vfe_device *vfe);
void msm_vfe_get_vfe_id(struct media_entity *entity, u8 *id);
void msm_vfe_get_vfe_line_id(struct media_entity *entity, enum vfe_line_id *id);
/*
* vfe_buf_add_pending - Add output buffer to list of pending
* @output: VFE output
* @buffer: Video buffer
*/
void vfe_buf_add_pending(struct vfe_output *output, struct camss_buffer *buffer);
struct camss_buffer *vfe_buf_get_pending(struct vfe_output *output);
/*
* vfe_disable - Disable streaming on VFE line
* @line: VFE line
*
* Return 0 on success or a negative error code otherwise
*/
int vfe_disable(struct vfe_line *line);
int vfe_flush_buffers(struct camss_video *vid, enum vb2_buffer_state state);
/*
* vfe_isr_comp_done - Process composite image done interrupt
* @vfe: VFE Device
* @comp: Composite image id
*/
void vfe_isr_comp_done(struct vfe_device *vfe, u8 comp);
void vfe_isr_reset_ack(struct vfe_device *vfe);
int vfe_put_output(struct vfe_line *line);
int vfe_release_wm(struct vfe_device *vfe, u8 wm);
int vfe_reserve_wm(struct vfe_device *vfe, enum vfe_line_id line_id);
extern const struct vfe_hw_ops vfe_ops_4_1;
extern const struct vfe_hw_ops vfe_ops_4_7;
extern const struct vfe_hw_ops vfe_ops_4_8;
......
......@@ -881,7 +881,7 @@ static int camss_register_entities(struct camss *camss)
for (i = 0; i < camss->ispif->line_num; i++)
for (k = 0; k < camss->vfe_num; k++)
for (j = 0; j < ARRAY_SIZE(camss->vfe[k].line); j++) {
for (j = 0; j < camss->vfe[k].line_num; j++) {
struct v4l2_subdev *ispif = &camss->ispif->line[i].subdev;
struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev;
......@@ -902,7 +902,7 @@ static int camss_register_entities(struct camss *camss)
} else {
for (i = 0; i < camss->csid_num; i++)
for (k = 0; k < camss->vfe_num; k++)
for (j = 0; j < ARRAY_SIZE(camss->vfe[k].line); j++) {
for (j = 0; j < camss->vfe[k].line_num; j++) {
struct v4l2_subdev *csid = &camss->csid[i].subdev;
struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment