media: rcar-vin: Store scaler in a function pointer
The scaler implementation is different between the VIN generations, and not all SoCs have a scaler. Currently only Gen2 scalers are supported. Prepare to add support for more scalers by storing the setup in a function pointer initialized at probe time. While at it move call site to after, instead of before, the generic capture setup, this have no effect on the Gen2 scaler but will be leveraged by the Gen3 scaler. Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
Родитель
f42a323252
Коммит
3ad69c610b
|
@ -1131,6 +1131,7 @@ static const struct rvin_info rcar_info_h1 = {
|
||||||
.use_mc = false,
|
.use_mc = false,
|
||||||
.max_width = 2048,
|
.max_width = 2048,
|
||||||
.max_height = 2048,
|
.max_height = 2048,
|
||||||
|
.scaler = rvin_scaler_gen2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct rvin_info rcar_info_m1 = {
|
static const struct rvin_info rcar_info_m1 = {
|
||||||
|
@ -1138,6 +1139,7 @@ static const struct rvin_info rcar_info_m1 = {
|
||||||
.use_mc = false,
|
.use_mc = false,
|
||||||
.max_width = 2048,
|
.max_width = 2048,
|
||||||
.max_height = 2048,
|
.max_height = 2048,
|
||||||
|
.scaler = rvin_scaler_gen2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct rvin_info rcar_info_gen2 = {
|
static const struct rvin_info rcar_info_gen2 = {
|
||||||
|
@ -1145,6 +1147,7 @@ static const struct rvin_info rcar_info_gen2 = {
|
||||||
.use_mc = false,
|
.use_mc = false,
|
||||||
.max_width = 2048,
|
.max_width = 2048,
|
||||||
.max_height = 2048,
|
.max_height = 2048,
|
||||||
|
.scaler = rvin_scaler_gen2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct rvin_group_route rcar_info_r8a774e1_routes[] = {
|
static const struct rvin_group_route rcar_info_r8a774e1_routes[] = {
|
||||||
|
@ -1408,13 +1411,17 @@ static int rcar_vin_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
platform_set_drvdata(pdev, vin);
|
platform_set_drvdata(pdev, vin);
|
||||||
|
|
||||||
if (vin->info->use_isp)
|
if (vin->info->use_isp) {
|
||||||
ret = rvin_isp_init(vin);
|
ret = rvin_isp_init(vin);
|
||||||
else if (vin->info->use_mc)
|
} else if (vin->info->use_mc) {
|
||||||
ret = rvin_csi2_init(vin);
|
ret = rvin_csi2_init(vin);
|
||||||
else
|
} else {
|
||||||
ret = rvin_parallel_init(vin);
|
ret = rvin_parallel_init(vin);
|
||||||
|
|
||||||
|
if (vin->info->scaler)
|
||||||
|
vin->scaler = vin->info->scaler;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
rvin_dma_unregister(vin);
|
rvin_dma_unregister(vin);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -160,9 +160,17 @@ static u32 rvin_read(struct rvin_dev *vin, u32 offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* Crop and Scaling Gen2
|
* Crop and Scaling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static bool rvin_scaler_needed(const struct rvin_dev *vin)
|
||||||
|
{
|
||||||
|
return !(vin->crop.width == vin->format.width &&
|
||||||
|
vin->compose.width == vin->format.width &&
|
||||||
|
vin->crop.height == vin->format.height &&
|
||||||
|
vin->compose.height == vin->format.height);
|
||||||
|
}
|
||||||
|
|
||||||
struct vin_coeff {
|
struct vin_coeff {
|
||||||
unsigned short xs_value;
|
unsigned short xs_value;
|
||||||
u32 coeff_set[24];
|
u32 coeff_set[24];
|
||||||
|
@ -535,7 +543,7 @@ static void rvin_set_coeff(struct rvin_dev *vin, unsigned short xs)
|
||||||
rvin_write(vin, p_set->coeff_set[23], VNC8C_REG);
|
rvin_write(vin, p_set->coeff_set[23], VNC8C_REG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rvin_crop_scale_comp_gen2(struct rvin_dev *vin)
|
void rvin_scaler_gen2(struct rvin_dev *vin)
|
||||||
{
|
{
|
||||||
unsigned int crop_height;
|
unsigned int crop_height;
|
||||||
u32 xs, ys;
|
u32 xs, ys;
|
||||||
|
@ -594,9 +602,8 @@ void rvin_crop_scale_comp(struct rvin_dev *vin)
|
||||||
rvin_write(vin, vin->crop.top, VNSLPRC_REG);
|
rvin_write(vin, vin->crop.top, VNSLPRC_REG);
|
||||||
rvin_write(vin, vin->crop.top + vin->crop.height - 1, VNELPRC_REG);
|
rvin_write(vin, vin->crop.top + vin->crop.height - 1, VNELPRC_REG);
|
||||||
|
|
||||||
/* TODO: Add support for the UDS scaler. */
|
if (vin->scaler)
|
||||||
if (vin->info->model != RCAR_GEN3)
|
vin->scaler(vin);
|
||||||
rvin_crop_scale_comp_gen2(vin);
|
|
||||||
|
|
||||||
fmt = rvin_format_from_pixel(vin, vin->format.pixelformat);
|
fmt = rvin_format_from_pixel(vin, vin->format.pixelformat);
|
||||||
stride = vin->format.bytesperline / fmt->bpp;
|
stride = vin->format.bytesperline / fmt->bpp;
|
||||||
|
@ -984,12 +991,12 @@ static int rvin_capture_start(struct rvin_dev *vin)
|
||||||
for (slot = 0; slot < HW_BUFFER_NUM; slot++)
|
for (slot = 0; slot < HW_BUFFER_NUM; slot++)
|
||||||
rvin_fill_hw_slot(vin, slot);
|
rvin_fill_hw_slot(vin, slot);
|
||||||
|
|
||||||
rvin_crop_scale_comp(vin);
|
|
||||||
|
|
||||||
ret = rvin_setup(vin);
|
ret = rvin_setup(vin);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
rvin_crop_scale_comp(vin);
|
||||||
|
|
||||||
vin_dbg(vin, "Starting to capture\n");
|
vin_dbg(vin, "Starting to capture\n");
|
||||||
|
|
||||||
/* Continuous Frame Capture Mode */
|
/* Continuous Frame Capture Mode */
|
||||||
|
@ -1234,9 +1241,16 @@ static int rvin_mc_validate_format(struct rvin_dev *vin, struct v4l2_subdev *sd,
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fmt.format.width != vin->format.width ||
|
if (rvin_scaler_needed(vin)) {
|
||||||
fmt.format.height != vin->format.height ||
|
if (!vin->scaler)
|
||||||
fmt.format.code != vin->mbus_code)
|
return -EPIPE;
|
||||||
|
} else {
|
||||||
|
if (fmt.format.width != vin->format.width ||
|
||||||
|
fmt.format.height != vin->format.height)
|
||||||
|
return -EPIPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fmt.format.code != vin->mbus_code)
|
||||||
return -EPIPE;
|
return -EPIPE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -477,6 +477,9 @@ static int rvin_g_selection(struct file *file, void *fh,
|
||||||
struct rvin_dev *vin = video_drvdata(file);
|
struct rvin_dev *vin = video_drvdata(file);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!vin->scaler)
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
|
||||||
if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -520,6 +523,9 @@ static int rvin_s_selection(struct file *file, void *fh,
|
||||||
};
|
};
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!vin->scaler)
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
|
||||||
if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
/* Max number on VIN instances that can be in a system */
|
/* Max number on VIN instances that can be in a system */
|
||||||
#define RCAR_VIN_NUM 32
|
#define RCAR_VIN_NUM 32
|
||||||
|
|
||||||
|
struct rvin_dev;
|
||||||
struct rvin_group;
|
struct rvin_group;
|
||||||
|
|
||||||
enum model_id {
|
enum model_id {
|
||||||
|
@ -155,6 +156,7 @@ struct rvin_group_route {
|
||||||
* @max_height: max input height the VIN supports
|
* @max_height: max input height the VIN supports
|
||||||
* @routes: list of possible routes from the CSI-2 recivers to
|
* @routes: list of possible routes from the CSI-2 recivers to
|
||||||
* all VINs. The list mush be NULL terminated.
|
* all VINs. The list mush be NULL terminated.
|
||||||
|
* @scaler: Optional scaler
|
||||||
*/
|
*/
|
||||||
struct rvin_info {
|
struct rvin_info {
|
||||||
enum model_id model;
|
enum model_id model;
|
||||||
|
@ -165,6 +167,7 @@ struct rvin_info {
|
||||||
unsigned int max_width;
|
unsigned int max_width;
|
||||||
unsigned int max_height;
|
unsigned int max_height;
|
||||||
const struct rvin_group_route *routes;
|
const struct rvin_group_route *routes;
|
||||||
|
void (*scaler)(struct rvin_dev *vin);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -203,6 +206,7 @@ struct rvin_info {
|
||||||
*
|
*
|
||||||
* @crop: active cropping
|
* @crop: active cropping
|
||||||
* @compose: active composing
|
* @compose: active composing
|
||||||
|
* @scaler: Optional scaler
|
||||||
* @std: active video standard of the video source
|
* @std: active video standard of the video source
|
||||||
*
|
*
|
||||||
* @alpha: Alpha component to fill in for supported pixel formats
|
* @alpha: Alpha component to fill in for supported pixel formats
|
||||||
|
@ -246,6 +250,7 @@ struct rvin_dev {
|
||||||
|
|
||||||
struct v4l2_rect crop;
|
struct v4l2_rect crop;
|
||||||
struct v4l2_rect compose;
|
struct v4l2_rect compose;
|
||||||
|
void (*scaler)(struct rvin_dev *vin);
|
||||||
v4l2_std_id std;
|
v4l2_std_id std;
|
||||||
|
|
||||||
unsigned int alpha;
|
unsigned int alpha;
|
||||||
|
@ -302,6 +307,7 @@ const struct rvin_video_format *rvin_format_from_pixel(struct rvin_dev *vin,
|
||||||
|
|
||||||
|
|
||||||
/* Cropping, composing and scaling */
|
/* Cropping, composing and scaling */
|
||||||
|
void rvin_scaler_gen2(struct rvin_dev *vin);
|
||||||
void rvin_crop_scale_comp(struct rvin_dev *vin);
|
void rvin_crop_scale_comp(struct rvin_dev *vin);
|
||||||
|
|
||||||
int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
|
int rvin_set_channel_routing(struct rvin_dev *vin, u8 chsel);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче