Skip to content

Commit

Permalink
media: camss: vfe: Add support for UYVY output from VFE on 8x96
Browse files Browse the repository at this point in the history
Add support to output UYVY formats from the VFE (via the PIX interface).
A configuration for the realign module in the VFE is added. As the
realign module is present on 8x96 but not on 8x16, this is supported
on 8x96 only.

Signed-off-by: Todor Tomov <[email protected]>
Signed-off-by: Hans Verkuil <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
todortomov authored and mchehab committed Aug 2, 2018
1 parent 07eeb34 commit 312e1c8
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 24 deletions.
6 changes: 6 additions & 0 deletions drivers/media/platform/qcom/camss/camss-vfe-4-1.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,11 @@ static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,
}
}

static void vfe_set_realign_cfg(struct vfe_device *vfe, struct vfe_line *line,
u8 enable)
{
/* empty */
}
static void vfe_set_rdi_cid(struct vfe_device *vfe, enum vfe_line_id id, u8 cid)
{
vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id),
Expand Down Expand Up @@ -989,6 +994,7 @@ const struct vfe_hw_ops vfe_ops_4_1 = {
.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,
Expand Down
129 changes: 109 additions & 20 deletions drivers/media/platform/qcom/camss/camss-vfe-4-7.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define VFE_0_MODULE_ZOOM_EN 0x04c
#define VFE_0_MODULE_ZOOM_EN_SCALE_ENC BIT(1)
#define VFE_0_MODULE_ZOOM_EN_CROP_ENC BIT(2)
#define VFE_0_MODULE_ZOOM_EN_REALIGN_BUF BIT(9)

#define VFE_0_CORE_CFG 0x050
#define VFE_0_CORE_CFG_PIXEL_PATTERN_YCBYCR 0x4
Expand Down Expand Up @@ -87,6 +88,9 @@

#define VFE_0_BUS_XBAR_CFG_x(x) (0x90 + 0x4 * ((x) / 2))
#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN BIT(2)
#define VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN BIT(3)
#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTRA (0x1 << 4)
#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER (0x2 << 4)
#define VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA (0x3 << 4)
#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT 8
#define VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA 0x0
Expand Down Expand Up @@ -221,6 +225,11 @@
#define VFE_0_CLAMP_ENC_MIN_CFG_CH1 (0x0 << 8)
#define VFE_0_CLAMP_ENC_MIN_CFG_CH2 (0x0 << 16)

#define VFE_0_REALIGN_BUF_CFG 0xaac
#define VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL BIT(2)
#define VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL BIT(3)
#define VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE BIT(4)

#define CAMIF_TIMEOUT_SLEEP_US 1000
#define CAMIF_TIMEOUT_ALL_US 1000000

Expand Down Expand Up @@ -311,7 +320,7 @@ static void vfe_wm_frame_based(struct vfe_device *vfe, u8 wm, u8 enable)

#define CALC_WORD(width, M, N) (((width) * (M) + (N) - 1) / (N))

static int vfe_word_per_line(u32 format, u32 pixel_per_line)
static int vfe_word_per_line_by_pixel(u32 format, u32 pixel_per_line)
{
int val = 0;

Expand All @@ -333,6 +342,11 @@ static int vfe_word_per_line(u32 format, u32 pixel_per_line)
return val;
}

static int vfe_word_per_line_by_bytes(u32 bytes_per_line)
{
return CALC_WORD(bytes_per_line, 1, 8);
}

static void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane,
u16 *width, u16 *height, u16 *bytesperline)
{
Expand All @@ -351,6 +365,15 @@ static void vfe_get_wm_sizes(struct v4l2_pix_format_mplane *pix, u8 plane,
*height = pix->height;
*bytesperline = pix->plane_fmt[0].bytesperline;
break;
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
case V4L2_PIX_FMT_VYUY:
case V4L2_PIX_FMT_UYVY:
*width = pix->width;
*height = pix->height;
*bytesperline = pix->plane_fmt[plane].bytesperline;
break;

}
}

Expand All @@ -365,15 +388,15 @@ static void vfe_wm_line_based(struct vfe_device *vfe, u32 wm,

vfe_get_wm_sizes(pix, plane, &width, &height, &bytesperline);

wpl = vfe_word_per_line(pix->pixelformat, width);
wpl = vfe_word_per_line_by_pixel(pix->pixelformat, width);

reg = height - 1;
reg |= ((wpl + 3) / 4 - 1) << 16;

writel_relaxed(reg, vfe->base +
VFE_0_BUS_IMAGE_MASTER_n_WR_IMAGE_SIZE(wm));

wpl = vfe_word_per_line(pix->pixelformat, bytesperline);
wpl = vfe_word_per_line_by_bytes(bytesperline);

reg = 0x3;
reg |= (height - 1) << 2;
Expand Down Expand Up @@ -536,32 +559,97 @@ static void vfe_set_xbar_cfg(struct vfe_device *vfe, struct vfe_output *output,
struct vfe_line *line = container_of(output, struct vfe_line, output);
u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
u32 reg;
unsigned int i;

for (i = 0; i < output->wm_num; i++) {
if (i == 0) {
reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA <<
VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;
} else if (i == 1) {
reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16)
reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;
}
switch (p) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_NV61:
reg = VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_LUMA <<
VFE_0_BUS_XBAR_CFG_x_M_SINGLE_STREAM_SEL_SHIFT;

if (output->wm_idx[0] % 2 == 1)
reg <<= 16;

if (enable)
vfe_reg_set(vfe,
VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
reg);
else
vfe_reg_clr(vfe,
VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
reg);

reg = VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;
if (p == V4L2_PIX_FMT_NV12 || p == V4L2_PIX_FMT_NV16)
reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;

if (output->wm_idx[1] % 2 == 1)
reg <<= 16;

if (output->wm_idx[i] % 2 == 1)
if (enable)
vfe_reg_set(vfe,
VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),
reg);
else
vfe_reg_clr(vfe,
VFE_0_BUS_XBAR_CFG_x(output->wm_idx[1]),
reg);
break;
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
case V4L2_PIX_FMT_VYUY:
case V4L2_PIX_FMT_UYVY:
reg = VFE_0_BUS_XBAR_CFG_x_M_REALIGN_BUF_EN;
reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_EN;

if (p == V4L2_PIX_FMT_YUYV || p == V4L2_PIX_FMT_YVYU)
reg |= VFE_0_BUS_XBAR_CFG_x_M_PAIR_STREAM_SWAP_INTER_INTRA;

if (output->wm_idx[0] % 2 == 1)
reg <<= 16;

if (enable)
vfe_reg_set(vfe,
VFE_0_BUS_XBAR_CFG_x(output->wm_idx[i]),
VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
reg);
else
vfe_reg_clr(vfe,
VFE_0_BUS_XBAR_CFG_x(output->wm_idx[i]),
VFE_0_BUS_XBAR_CFG_x(output->wm_idx[0]),
reg);
break;
default:
break;
}
}

static void vfe_set_realign_cfg(struct vfe_device *vfe, struct vfe_line *line,
u8 enable)
{
u32 p = line->video_out.active_fmt.fmt.pix_mp.pixelformat;
u32 val = VFE_0_MODULE_ZOOM_EN_REALIGN_BUF;

if (p != V4L2_PIX_FMT_YUYV && p != V4L2_PIX_FMT_YVYU &&
p != V4L2_PIX_FMT_VYUY && p != V4L2_PIX_FMT_UYVY)
return;

if (enable) {
vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val);
} else {
vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val);
return;
}

val = VFE_0_REALIGN_BUF_CFG_HSUB_ENABLE;

if (p == V4L2_PIX_FMT_UYVY || p == V4L2_PIX_FMT_YUYV)
val |= VFE_0_REALIGN_BUF_CFG_CR_ODD_PIXEL;
else
val |= VFE_0_REALIGN_BUF_CFG_CB_ODD_PIXEL;

writel_relaxed(val, vfe->base + VFE_0_REALIGN_BUF_CFG);
}

static void vfe_set_rdi_cid(struct vfe_device *vfe, enum vfe_line_id id, u8 cid)
{
vfe_reg_clr(vfe, VFE_0_RDI_CFG_x(id),
Expand Down Expand Up @@ -911,11 +999,11 @@ static void vfe_set_module_cfg(struct vfe_device *vfe, u8 enable)
VFE_0_MODULE_ZOOM_EN_CROP_ENC;

if (enable) {
writel_relaxed(val_lens, vfe->base + VFE_0_MODULE_LENS_EN);
writel_relaxed(val_zoom, vfe->base + VFE_0_MODULE_ZOOM_EN);
vfe_reg_set(vfe, VFE_0_MODULE_LENS_EN, val_lens);
vfe_reg_set(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);
} else {
writel_relaxed(0x0, vfe->base + VFE_0_MODULE_LENS_EN);
writel_relaxed(0x0, vfe->base + VFE_0_MODULE_ZOOM_EN);
vfe_reg_clr(vfe, VFE_0_MODULE_LENS_EN, val_lens);
vfe_reg_clr(vfe, VFE_0_MODULE_ZOOM_EN, val_zoom);
}
}

Expand Down Expand Up @@ -1028,6 +1116,7 @@ const struct vfe_hw_ops vfe_ops_4_7 = {
.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,
Expand Down
31 changes: 27 additions & 4 deletions drivers/media/platform/qcom/camss/camss-vfe.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
{
u32 src_code[] = {
MEDIA_BUS_FMT_YUYV8_2X8,
MEDIA_BUS_FMT_YVYU8_2X8,
MEDIA_BUS_FMT_UYVY8_2X8,
MEDIA_BUS_FMT_VYUY8_2X8,
MEDIA_BUS_FMT_YUYV8_1_5X8,
};

Expand All @@ -213,6 +216,9 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
{
u32 src_code[] = {
MEDIA_BUS_FMT_YVYU8_2X8,
MEDIA_BUS_FMT_YUYV8_2X8,
MEDIA_BUS_FMT_UYVY8_2X8,
MEDIA_BUS_FMT_VYUY8_2X8,
MEDIA_BUS_FMT_YVYU8_1_5X8,
};

Expand All @@ -223,6 +229,9 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
{
u32 src_code[] = {
MEDIA_BUS_FMT_UYVY8_2X8,
MEDIA_BUS_FMT_YUYV8_2X8,
MEDIA_BUS_FMT_YVYU8_2X8,
MEDIA_BUS_FMT_VYUY8_2X8,
MEDIA_BUS_FMT_UYVY8_1_5X8,
};

Expand All @@ -233,6 +242,9 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
{
u32 src_code[] = {
MEDIA_BUS_FMT_VYUY8_2X8,
MEDIA_BUS_FMT_YUYV8_2X8,
MEDIA_BUS_FMT_YVYU8_2X8,
MEDIA_BUS_FMT_UYVY8_2X8,
MEDIA_BUS_FMT_VYUY8_1_5X8,
};

Expand Down Expand Up @@ -308,10 +320,6 @@ static void vfe_init_outputs(struct vfe_device *vfe)
output->buf[0] = NULL;
output->buf[1] = NULL;
INIT_LIST_HEAD(&output->pending_bufs);

output->wm_num = 1;
if (vfe->line[i].id == VFE_LINE_PIX)
output->wm_num = 2;
}
}

Expand Down Expand Up @@ -567,6 +575,7 @@ static int vfe_get_output(struct vfe_line *line)
{
struct vfe_device *vfe = to_vfe(line);
struct vfe_output *output;
struct v4l2_format *f = &line->video_out.active_fmt;
unsigned long flags;
int i;
int wm_idx;
Expand All @@ -582,6 +591,18 @@ static int vfe_get_output(struct vfe_line *line)

output->active_buf = 0;

switch (f->fmt.pix_mp.pixelformat) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_NV61:
output->wm_num = 2;
break;
default:
output->wm_num = 1;
break;
}

for (i = 0; i < output->wm_num; i++) {
wm_idx = vfe_reserve_wm(vfe, line->id);
if (wm_idx < 0) {
Expand Down Expand Up @@ -712,6 +733,7 @@ static int vfe_enable_output(struct vfe_line *line)
ops->enable_irq_pix_line(vfe, 0, line->id, 1);
ops->set_module_cfg(vfe, 1);
ops->set_camif_cfg(vfe, line);
ops->set_realign_cfg(vfe, line, 1);
ops->set_xbar_cfg(vfe, output, 1);
ops->set_demux_cfg(vfe, line);
ops->set_scale_cfg(vfe, line);
Expand Down Expand Up @@ -776,6 +798,7 @@ static int vfe_disable_output(struct vfe_line *line)

ops->enable_irq_pix_line(vfe, 0, line->id, 0);
ops->set_module_cfg(vfe, 0);
ops->set_realign_cfg(vfe, line, 0);
ops->set_xbar_cfg(vfe, output, 0);

ops->set_camif_cmd(vfe, 0);
Expand Down
2 changes: 2 additions & 0 deletions drivers/media/platform/qcom/camss/camss-vfe.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ struct vfe_hw_ops {
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 (*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);
Expand Down
8 changes: 8 additions & 0 deletions drivers/media/platform/qcom/camss/camss-video.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ static const struct camss_format_info formats_pix_8x96[] = {
{ { 1, 1 } }, { { 1, 2 } }, { 8 } },
{ MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_NV61, 1,
{ { 1, 1 } }, { { 1, 2 } }, { 8 } },
{ MEDIA_BUS_FMT_UYVY8_2X8, V4L2_PIX_FMT_UYVY, 1,
{ { 1, 1 } }, { { 1, 1 } }, { 16 } },
{ MEDIA_BUS_FMT_VYUY8_2X8, V4L2_PIX_FMT_VYUY, 1,
{ { 1, 1 } }, { { 1, 1 } }, { 16 } },
{ MEDIA_BUS_FMT_YUYV8_2X8, V4L2_PIX_FMT_YUYV, 1,
{ { 1, 1 } }, { { 1, 1 } }, { 16 } },
{ MEDIA_BUS_FMT_YVYU8_2X8, V4L2_PIX_FMT_YVYU, 1,
{ { 1, 1 } }, { { 1, 1 } }, { 16 } },
};

/* -----------------------------------------------------------------------------
Expand Down

0 comments on commit 312e1c8

Please sign in to comment.