diff options
Diffstat (limited to 'drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c')
| -rw-r--r-- | drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c | 180 |
1 files changed, 154 insertions, 26 deletions
diff --git a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c index ac8ebae4ed07..5f2c87858bfe 100644 --- a/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c +++ b/drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c @@ -6,34 +6,140 @@ */ #include <linux/delay.h> -#include "rzg2l-cru.h" +#include <media/mipi-csi2.h> -struct rzg2l_cru_ip_format { - u32 code; - unsigned int datatype; - unsigned int bpp; -}; +#include "rzg2l-cru.h" +#include "rzg2l-cru-regs.h" static const struct rzg2l_cru_ip_format rzg2l_cru_ip_formats[] = { - { .code = MEDIA_BUS_FMT_UYVY8_1X16, .datatype = 0x1e, .bpp = 16 }, + { + .codes = { + MEDIA_BUS_FMT_UYVY8_1X16, + }, + .datatype = MIPI_CSI2_DT_YUV422_8B, + .format = V4L2_PIX_FMT_UYVY, + .icndmr = ICnDMR_YCMODE_UYVY, + .yuv = true, + }, + { + .codes = { + MEDIA_BUS_FMT_SBGGR8_1X8, + }, + .format = V4L2_PIX_FMT_SBGGR8, + .datatype = MIPI_CSI2_DT_RAW8, + .icndmr = 0, + .yuv = false, + }, + { + .codes = { + MEDIA_BUS_FMT_SGBRG8_1X8, + }, + .format = V4L2_PIX_FMT_SGBRG8, + .datatype = MIPI_CSI2_DT_RAW8, + .icndmr = 0, + .yuv = false, + }, + { + .codes = { + MEDIA_BUS_FMT_SGRBG8_1X8, + }, + .format = V4L2_PIX_FMT_SGRBG8, + .datatype = MIPI_CSI2_DT_RAW8, + .icndmr = 0, + .yuv = false, + }, + { + .codes = { + MEDIA_BUS_FMT_SRGGB8_1X8, + }, + .format = V4L2_PIX_FMT_SRGGB8, + .datatype = MIPI_CSI2_DT_RAW8, + .icndmr = 0, + .yuv = false, + }, + { + .codes = { + MEDIA_BUS_FMT_SBGGR10_1X10, + MEDIA_BUS_FMT_SGBRG10_1X10, + MEDIA_BUS_FMT_SGRBG10_1X10, + MEDIA_BUS_FMT_SRGGB10_1X10 + }, + .format = V4L2_PIX_FMT_RAW_CRU10, + .datatype = MIPI_CSI2_DT_RAW10, + .icndmr = 0, + .yuv = false, + }, + { + .codes = { + MEDIA_BUS_FMT_SBGGR12_1X12, + MEDIA_BUS_FMT_SGBRG12_1X12, + MEDIA_BUS_FMT_SGRBG12_1X12, + MEDIA_BUS_FMT_SRGGB12_1X12 + }, + .format = V4L2_PIX_FMT_RAW_CRU12, + .datatype = MIPI_CSI2_DT_RAW12, + .icndmr = 0, + .yuv = false, + }, + { + .codes = { + MEDIA_BUS_FMT_SBGGR14_1X14, + MEDIA_BUS_FMT_SGBRG14_1X14, + MEDIA_BUS_FMT_SGRBG14_1X14, + MEDIA_BUS_FMT_SRGGB14_1X14 + }, + .format = V4L2_PIX_FMT_RAW_CRU14, + .datatype = MIPI_CSI2_DT_RAW14, + .icndmr = 0, + .yuv = false, + }, }; -enum rzg2l_csi2_pads { - RZG2L_CRU_IP_SINK = 0, - RZG2L_CRU_IP_SOURCE, -}; +const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int code) +{ + unsigned int i, j; + + for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++) { + for (j = 0; j < ARRAY_SIZE(rzg2l_cru_ip_formats[i].codes); j++) { + if (rzg2l_cru_ip_formats[i].codes[j] == code) + return &rzg2l_cru_ip_formats[i]; + } + } -static const struct rzg2l_cru_ip_format *rzg2l_cru_ip_code_to_fmt(unsigned int code) + return NULL; +} + +const struct rzg2l_cru_ip_format *rzg2l_cru_ip_format_to_fmt(u32 format) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++) - if (rzg2l_cru_ip_formats[i].code == code) + for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++) { + if (rzg2l_cru_ip_formats[i].format == format) return &rzg2l_cru_ip_formats[i]; + } return NULL; } +const struct rzg2l_cru_ip_format *rzg2l_cru_ip_index_to_fmt(u32 index) +{ + if (index >= ARRAY_SIZE(rzg2l_cru_ip_formats)) + return NULL; + + return &rzg2l_cru_ip_formats[index]; +} + +bool rzg2l_cru_ip_fmt_supports_mbus_code(const struct rzg2l_cru_ip_format *fmt, + unsigned int code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(fmt->codes); i++) + if (fmt->codes[i] == code) + return true; + + return false; +} struct v4l2_mbus_framefmt *rzg2l_cru_ip_get_src_fmt(struct rzg2l_cru_dev *cru) { struct v4l2_subdev_state *state; @@ -97,6 +203,8 @@ static int rzg2l_cru_ip_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_format *fmt) { + struct rzg2l_cru_dev *cru = v4l2_get_subdevdata(sd); + const struct rzg2l_cru_info *info = cru->info; struct v4l2_mbus_framefmt *src_format; struct v4l2_mbus_framefmt *sink_format; @@ -109,7 +217,7 @@ static int rzg2l_cru_ip_set_format(struct v4l2_subdev *sd, sink_format = v4l2_subdev_state_get_format(state, fmt->pad); if (!rzg2l_cru_ip_code_to_fmt(fmt->format.code)) - sink_format->code = rzg2l_cru_ip_formats[0].code; + sink_format->code = rzg2l_cru_ip_formats[0].codes[0]; else sink_format->code = fmt->format.code; @@ -119,9 +227,9 @@ static int rzg2l_cru_ip_set_format(struct v4l2_subdev *sd, sink_format->ycbcr_enc = fmt->format.ycbcr_enc; sink_format->quantization = fmt->format.quantization; sink_format->width = clamp_t(u32, fmt->format.width, - RZG2L_CRU_MIN_INPUT_WIDTH, RZG2L_CRU_MAX_INPUT_WIDTH); + RZG2L_CRU_MIN_INPUT_WIDTH, info->max_width); sink_format->height = clamp_t(u32, fmt->format.height, - RZG2L_CRU_MIN_INPUT_HEIGHT, RZG2L_CRU_MAX_INPUT_HEIGHT); + RZG2L_CRU_MIN_INPUT_HEIGHT, info->max_height); fmt->format = *sink_format; @@ -135,27 +243,45 @@ static int rzg2l_cru_ip_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_mbus_code_enum *code) { - if (code->index >= ARRAY_SIZE(rzg2l_cru_ip_formats)) - return -EINVAL; + unsigned int index = code->index; + unsigned int i, j; - code->code = rzg2l_cru_ip_formats[code->index].code; - return 0; + for (i = 0; i < ARRAY_SIZE(rzg2l_cru_ip_formats); i++) { + const struct rzg2l_cru_ip_format *fmt = &rzg2l_cru_ip_formats[i]; + + for (j = 0; j < ARRAY_SIZE(fmt->codes); j++) { + if (!fmt->codes[j]) + continue; + + if (!index) { + code->code = fmt->codes[j]; + return 0; + } + + index--; + } + } + + return -EINVAL; } static int rzg2l_cru_ip_enum_frame_size(struct v4l2_subdev *sd, struct v4l2_subdev_state *state, struct v4l2_subdev_frame_size_enum *fse) { + struct rzg2l_cru_dev *cru = v4l2_get_subdevdata(sd); + const struct rzg2l_cru_info *info = cru->info; + if (fse->index != 0) return -EINVAL; - if (fse->code != MEDIA_BUS_FMT_UYVY8_1X16) + if (!rzg2l_cru_ip_code_to_fmt(fse->code)) return -EINVAL; fse->min_width = RZG2L_CRU_MIN_INPUT_WIDTH; fse->min_height = RZG2L_CRU_MIN_INPUT_HEIGHT; - fse->max_width = RZG2L_CRU_MAX_INPUT_WIDTH; - fse->max_height = RZG2L_CRU_MAX_INPUT_HEIGHT; + fse->max_width = info->max_width; + fse->max_height = info->max_height; return 0; } @@ -217,8 +343,10 @@ int rzg2l_cru_ip_subdev_register(struct rzg2l_cru_dev *cru) ip->subdev.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER; ip->subdev.entity.ops = &rzg2l_cru_ip_entity_ops; - ip->pads[0].flags = MEDIA_PAD_FL_SINK; - ip->pads[1].flags = MEDIA_PAD_FL_SOURCE; + ip->pads[RZG2L_CRU_IP_SINK].flags = MEDIA_PAD_FL_SINK | + MEDIA_PAD_FL_MUST_CONNECT; + ip->pads[RZG2L_CRU_IP_SOURCE].flags = MEDIA_PAD_FL_SOURCE | + MEDIA_PAD_FL_MUST_CONNECT; ret = media_entity_pads_init(&ip->subdev.entity, 2, ip->pads); if (ret) |
