Commit 6fd206cb authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

[media] omap3isp: preview: Add support for non-GRBG Bayer patterns

Rearrange the CFA interpolation coefficients table based on the Bayer
pattern. Support for non-Bayer CFA patterns is dropped as they were not
correctly supported, and have never been tested.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: default avatarSakari Ailus <sakari.ailus@iki.fi>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ac9dad93
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
* 02110-1301 USA * 02110-1301 USA
*/ */
244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244, { 244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244,
248, 0, 0, 0, 0, 40, 0, 0, 244, 12, 250, 4, 0, 27, 0, 250, 248, 0, 0, 0, 0, 40, 0, 0, 244, 12, 250, 4, 0, 27, 0, 250,
247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248, 247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248,
244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244, 244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244,
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248, 247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248,
244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244, 244, 0, 247, 0, 12, 27, 36, 247, 250, 0, 27, 0, 4, 250, 12, 244,
248, 0, 0, 0, 0, 40, 0, 0, 244, 12, 250, 4, 0, 27, 0, 250, 248, 0, 0, 0, 0, 40, 0, 0, 244, 12, 250, 4, 0, 27, 0, 250,
247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248, 247, 36, 27, 12, 0, 247, 0, 244, 0, 0, 40, 0, 0, 0, 0, 248 },
0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4, { 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4,
0, 0, 0, 248, 0, 0, 40, 0, 4, 250, 12, 244, 250, 0, 27, 0, 0, 0, 0, 248, 0, 0, 40, 0, 4, 250, 12, 244, 250, 0, 27, 0,
12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0, 12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0,
0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4, 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4,
...@@ -40,8 +40,8 @@ ...@@ -40,8 +40,8 @@
12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0, 12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0,
0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4, 0, 247, 0, 244, 247, 36, 27, 12, 0, 27, 0, 250, 244, 12, 250, 4,
0, 0, 0, 248, 0, 0, 40, 0, 4, 250, 12, 244, 250, 0, 27, 0, 0, 0, 0, 248, 0, 0, 40, 0, 4, 250, 12, 244, 250, 0, 27, 0,
12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0, 12, 27, 36, 247, 244, 0, 247, 0, 0, 40, 0, 0, 248, 0, 0, 0 },
4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0, { 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0,
0, 0, 0, 248, 0, 0, 40, 0, 0, 247, 0, 244, 247, 36, 27, 12, 0, 0, 0, 248, 0, 0, 40, 0, 0, 247, 0, 244, 247, 36, 27, 12,
0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0, 0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0,
4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0, 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0,
...@@ -49,8 +49,8 @@ ...@@ -49,8 +49,8 @@
0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0, 0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0,
4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0, 4, 250, 12, 244, 250, 0, 27, 0, 12, 27, 36, 247, 244, 0, 247, 0,
0, 0, 0, 248, 0, 0, 40, 0, 0, 247, 0, 244, 247, 36, 27, 12, 0, 0, 0, 248, 0, 0, 40, 0, 0, 247, 0, 244, 247, 36, 27, 12,
0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0, 0, 27, 0, 250, 244, 12, 250, 4, 0, 40, 0, 0, 248, 0, 0, 0 },
244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244, { 244,12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244,
248, 0, 0, 0, 0, 40, 0, 0, 244, 0, 247, 0, 12, 27, 36, 247, 248, 0, 0, 0, 0, 40, 0, 0, 244, 0, 247, 0, 12, 27, 36, 247,
250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248, 250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248,
244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244, 244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244,
...@@ -58,4 +58,4 @@ ...@@ -58,4 +58,4 @@
250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248, 250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248,
244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244, 244, 12, 250, 4, 0, 27, 0, 250, 247, 36, 27, 12, 0, 247, 0, 244,
248, 0, 0, 0, 0, 40, 0, 0, 244, 0, 247, 0, 12, 27, 36, 247, 248, 0, 0, 0, 0, 40, 0, 0, 244, 0, 247, 0, 12, 27, 36, 247,
250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248 250, 0, 27, 0, 4, 250, 12, 244, 0, 0, 40, 0, 0, 0, 0, 248 },
...@@ -131,7 +131,7 @@ static struct omap3isp_prev_csc flr_prev_csc = { ...@@ -131,7 +131,7 @@ static struct omap3isp_prev_csc flr_prev_csc = {
* CFA Filter Coefficient Table * CFA Filter Coefficient Table
* *
*/ */
static u32 cfa_coef_table[] = { static u32 cfa_coef_table[4][OMAP3ISP_PREV_CFA_BLK_SIZE] = {
#include "cfa_coef_table.h" #include "cfa_coef_table.h"
}; };
...@@ -237,19 +237,27 @@ static void preview_enable_hmed(struct isp_prev_device *prev, bool enable) ...@@ -237,19 +237,27 @@ static void preview_enable_hmed(struct isp_prev_device *prev, bool enable)
} }
/* /*
* preview_config_cfa - Configure CFA Interpolation * preview_config_cfa - Configure CFA Interpolation for Bayer formats
*/ *
static void * The CFA table is organised in four blocks, one per Bayer component. The
preview_config_cfa(struct isp_prev_device *prev, * hardware expects blocks to follow the Bayer order of the input data, while
const struct prev_params *params) * the driver stores the table in GRBG order in memory. The blocks need to be
{ * reordered to support non-GRBG Bayer patterns.
struct isp_device *isp = to_isp_device(prev); */
static void preview_config_cfa(struct isp_prev_device *prev,
const struct prev_params *params)
{
static const unsigned int cfa_coef_order[4][4] = {
{ 0, 1, 2, 3 }, /* GRBG */
{ 1, 0, 3, 2 }, /* RGGB */
{ 2, 3, 0, 1 }, /* BGGR */
{ 3, 2, 1, 0 }, /* GBRG */
};
const unsigned int *order = cfa_coef_order[prev->params.cfa_order];
const struct omap3isp_prev_cfa *cfa = &params->cfa; const struct omap3isp_prev_cfa *cfa = &params->cfa;
struct isp_device *isp = to_isp_device(prev);
unsigned int i; unsigned int i;
unsigned int j;
isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_CFAFMT_MASK,
cfa->format << ISPPRV_PCR_CFAFMT_SHIFT);
isp_reg_writel(isp, isp_reg_writel(isp,
(cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) | (cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
...@@ -259,9 +267,12 @@ preview_config_cfa(struct isp_prev_device *prev, ...@@ -259,9 +267,12 @@ preview_config_cfa(struct isp_prev_device *prev,
isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR, isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR,
OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR); OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
for (i = 0; i < OMAP3ISP_PREV_CFA_TBL_SIZE; i++) { for (i = 0; i < 4; ++i) {
isp_reg_writel(isp, cfa->table[i], const __u32 *block = cfa->table[order[i]];
OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
for (j = 0; j < OMAP3ISP_PREV_CFA_BLK_SIZE; ++j)
isp_reg_writel(isp, block[j], OMAP3_ISP_IOMEM_PREV,
ISPPRV_SET_TBL_DATA);
} }
} }
...@@ -993,42 +1004,60 @@ preview_config_ycpos(struct isp_prev_device *prev, ...@@ -993,42 +1004,60 @@ preview_config_ycpos(struct isp_prev_device *prev,
static void preview_config_averager(struct isp_prev_device *prev, u8 average) static void preview_config_averager(struct isp_prev_device *prev, u8 average)
{ {
struct isp_device *isp = to_isp_device(prev); struct isp_device *isp = to_isp_device(prev);
struct prev_params *params;
int reg = 0;
params = (prev->params.active & OMAP3ISP_PREV_CFA)
? &prev->params.params[0] : &prev->params.params[1];
if (params->cfa.format == OMAP3ISP_CFAFMT_BAYER) isp_reg_writel(isp, ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
reg = ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT | ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT | average, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
average;
else if (params->cfa.format == OMAP3ISP_CFAFMT_RGBFOVEON)
reg = ISPPRV_AVE_EVENDIST_3 << ISPPRV_AVE_EVENDIST_SHIFT |
ISPPRV_AVE_ODDDIST_3 << ISPPRV_AVE_ODDDIST_SHIFT |
average;
isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
} }
/* /*
* preview_config_input_format - Configure the input format * preview_config_input_format - Configure the input format
* @prev: The preview engine * @prev: The preview engine
* @format: Format on the preview engine sink pad * @format: Format on the preview engine sink pad
* *
* Enable CFA interpolation for Bayer formats and disable it for greyscale * Enable and configure CFA interpolation for Bayer formats and disable it for
* formats. * greyscale formats.
*
* The CFA table is organised in four blocks, one per Bayer component. The
* hardware expects blocks to follow the Bayer order of the input data, while
* the driver stores the table in GRBG order in memory. The blocks need to be
* reordered to support non-GRBG Bayer patterns.
*/ */
static void preview_config_input_format(struct isp_prev_device *prev, static void preview_config_input_format(struct isp_prev_device *prev,
const struct v4l2_mbus_framefmt *format) const struct v4l2_mbus_framefmt *format)
{ {
struct isp_device *isp = to_isp_device(prev); struct isp_device *isp = to_isp_device(prev);
struct prev_params *params;
if (format->code != V4L2_MBUS_FMT_Y10_1X10) switch (format->code) {
isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, case V4L2_MBUS_FMT_SGRBG10_1X10:
ISPPRV_PCR_CFAEN); prev->params.cfa_order = 0;
else break;
case V4L2_MBUS_FMT_SRGGB10_1X10:
prev->params.cfa_order = 1;
break;
case V4L2_MBUS_FMT_SBGGR10_1X10:
prev->params.cfa_order = 2;
break;
case V4L2_MBUS_FMT_SGBRG10_1X10:
prev->params.cfa_order = 3;
break;
default:
/* Disable CFA for non-Bayer formats. */
isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_CFAEN); ISPPRV_PCR_CFAEN);
return;
}
isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN);
isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_CFAFMT_MASK, ISPPRV_PCR_CFAFMT_BAYER);
params = (prev->params.active & OMAP3ISP_PREV_CFA)
? &prev->params.params[0] : &prev->params.params[1];
preview_config_cfa(prev, params);
} }
/* /*
...@@ -1371,22 +1400,6 @@ static void preview_configure(struct isp_prev_device *prev) ...@@ -1371,22 +1400,6 @@ static void preview_configure(struct isp_prev_device *prev)
active = prev->params.active; active = prev->params.active;
spin_unlock_irqrestore(&prev->params.lock, flags); spin_unlock_irqrestore(&prev->params.lock, flags);
preview_setup_hw(prev, update, active);
if (prev->output & PREVIEW_OUTPUT_MEMORY)
isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_SDRPORT);
else
isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_SDRPORT);
if (prev->output & PREVIEW_OUTPUT_RESIZER)
isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_RSZPORT);
else
isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_RSZPORT);
/* PREV_PAD_SINK */ /* PREV_PAD_SINK */
format = &prev->formats[PREV_PAD_SINK]; format = &prev->formats[PREV_PAD_SINK];
...@@ -1401,9 +1414,25 @@ static void preview_configure(struct isp_prev_device *prev) ...@@ -1401,9 +1414,25 @@ static void preview_configure(struct isp_prev_device *prev)
preview_config_inlineoffset(prev, preview_config_inlineoffset(prev,
ALIGN(format->width, 0x20) * 2); ALIGN(format->width, 0x20) * 2);
preview_setup_hw(prev, update, active);
/* PREV_PAD_SOURCE */ /* PREV_PAD_SOURCE */
format = &prev->formats[PREV_PAD_SOURCE]; format = &prev->formats[PREV_PAD_SOURCE];
if (prev->output & PREVIEW_OUTPUT_MEMORY)
isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_SDRPORT);
else
isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_SDRPORT);
if (prev->output & PREVIEW_OUTPUT_RESIZER)
isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_RSZPORT);
else
isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
ISPPRV_PCR_RSZPORT);
if (prev->output & PREVIEW_OUTPUT_MEMORY) if (prev->output & PREVIEW_OUTPUT_MEMORY)
preview_config_outlineoffset(prev, preview_config_outlineoffset(prev,
ALIGN(format->width, 0x10) * 2); ALIGN(format->width, 0x10) * 2);
......
...@@ -144,6 +144,7 @@ struct isp_prev_device { ...@@ -144,6 +144,7 @@ struct isp_prev_device {
struct isp_video video_out; struct isp_video video_out;
struct { struct {
unsigned int cfa_order;
struct prev_params params[2]; struct prev_params params[2];
u32 active; u32 active;
spinlock_t lock; spinlock_t lock;
......
...@@ -437,6 +437,7 @@ struct omap3isp_ccdc_update_config { ...@@ -437,6 +437,7 @@ struct omap3isp_ccdc_update_config {
#define OMAP3ISP_PREV_NF_TBL_SIZE 64 #define OMAP3ISP_PREV_NF_TBL_SIZE 64
#define OMAP3ISP_PREV_CFA_TBL_SIZE 576 #define OMAP3ISP_PREV_CFA_TBL_SIZE 576
#define OMAP3ISP_PREV_CFA_BLK_SIZE (OMAP3ISP_PREV_CFA_TBL_SIZE / 4)
#define OMAP3ISP_PREV_GAMMA_TBL_SIZE 1024 #define OMAP3ISP_PREV_GAMMA_TBL_SIZE 1024
#define OMAP3ISP_PREV_YENH_TBL_SIZE 128 #define OMAP3ISP_PREV_YENH_TBL_SIZE 128
...@@ -478,7 +479,7 @@ struct omap3isp_prev_cfa { ...@@ -478,7 +479,7 @@ struct omap3isp_prev_cfa {
enum omap3isp_cfa_fmt format; enum omap3isp_cfa_fmt format;
__u8 gradthrs_vert; __u8 gradthrs_vert;
__u8 gradthrs_horz; __u8 gradthrs_horz;
__u32 table[OMAP3ISP_PREV_CFA_TBL_SIZE]; __u32 table[4][OMAP3ISP_PREV_CFA_BLK_SIZE];
}; };
/** /**
......
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