diff options
Diffstat (limited to 'drivers/media/platform/qcom')
42 files changed, 3202 insertions, 1641 deletions
diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index 4e2222358973..e636968a1126 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -14,10 +14,11 @@ qcom-camss-objs += \ camss-vfe-4-1.o \ camss-vfe-4-7.o \ camss-vfe-4-8.o \ - camss-vfe-170.o \ + camss-vfe-17x.o \ camss-vfe-480.o \ camss-vfe-gen1.o \ camss-vfe.o \ camss-video.o \ + camss-format.o \ obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom-camss.o diff --git a/drivers/media/platform/qcom/camss/camss-csid-4-1.c b/drivers/media/platform/qcom/camss/camss-csid-4-1.c index dd49a40e6a70..c95861420502 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-4-1.c +++ b/drivers/media/platform/qcom/camss/camss-csid-4-1.c @@ -45,128 +45,6 @@ #define CAMSS_CSID_TG_DT_n_CGG_1(n) (0x0b0 + 0xc * (n)) #define CAMSS_CSID_TG_DT_n_CGG_2(n) (0x0b4 + 0xc * (n)) -static const struct csid_format csid_formats[] = { - { - MEDIA_BUS_FMT_UYVY8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_VYUY8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_YUYV8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_YVYU8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_SBGGR8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SBGGR10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SBGGR12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_Y10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, -}; - static void csid_configure_stream(struct csid_device *csid, u8 enable) { struct csid_testgen_config *tg = &csid->testgen; @@ -174,7 +52,7 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) if (enable) { struct v4l2_mbus_framefmt *input_format; - const struct csid_format *format; + const struct csid_format_info *format; u8 vc = 0; /* Virtual Channel 0 */ u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */ u8 dt_shift; @@ -184,7 +62,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) u32 num_lines, num_bytes_per_line; input_format = &csid->fmt[MSM_CSID_PAD_SRC]; - format = csid_get_fmt_entry(csid->formats, csid->nformats, + format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, input_format->code); num_bytes_per_line = input_format->width * format->bpp * format->spp / 8; num_lines = input_format->height; @@ -211,7 +90,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) struct csid_phy_config *phy = &csid->phy; input_format = &csid->fmt[MSM_CSID_PAD_SINK]; - format = csid_get_fmt_entry(csid->formats, csid->nformats, + format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, input_format->code); val = phy->lane_cnt - 1; @@ -311,8 +191,6 @@ static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code, static void csid_subdev_init(struct csid_device *csid) { - csid->formats = csid_formats; - csid->nformats = ARRAY_SIZE(csid_formats); csid->testgen.modes = csid_testgen_modes; csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN1; } diff --git a/drivers/media/platform/qcom/camss/camss-csid-4-7.c b/drivers/media/platform/qcom/camss/camss-csid-4-7.c index 6b26e036294e..08578a143688 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-4-7.c +++ b/drivers/media/platform/qcom/camss/camss-csid-4-7.c @@ -44,156 +44,6 @@ #define CAMSS_CSID_TG_DT_n_CGG_1(n) (0x0b8 + 0xc * (n)) #define CAMSS_CSID_TG_DT_n_CGG_2(n) (0x0bc + 0xc * (n)) -static const struct csid_format csid_formats[] = { - { - MEDIA_BUS_FMT_UYVY8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_VYUY8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_YUYV8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_YVYU8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_SBGGR8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SBGGR10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SBGGR12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SBGGR14_1X14, - DATA_TYPE_RAW_14BIT, - DECODE_FORMAT_UNCOMPRESSED_14_BIT, - 14, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG14_1X14, - DATA_TYPE_RAW_14BIT, - DECODE_FORMAT_UNCOMPRESSED_14_BIT, - 14, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG14_1X14, - DATA_TYPE_RAW_14BIT, - DECODE_FORMAT_UNCOMPRESSED_14_BIT, - 14, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB14_1X14, - DATA_TYPE_RAW_14BIT, - DECODE_FORMAT_UNCOMPRESSED_14_BIT, - 14, - 1, - }, - { - MEDIA_BUS_FMT_Y10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, -}; - static void csid_configure_stream(struct csid_device *csid, u8 enable) { struct csid_testgen_config *tg = &csid->testgen; @@ -203,7 +53,7 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) if (enable) { struct v4l2_mbus_framefmt *input_format; - const struct csid_format *format; + const struct csid_format_info *format; u8 vc = 0; /* Virtual Channel 0 */ u8 cid = vc * 4; /* id of Virtual Channel and Data Type set */ u8 dt_shift; @@ -213,7 +63,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) u32 num_bytes_per_line, num_lines; input_format = &csid->fmt[MSM_CSID_PAD_SRC]; - format = csid_get_fmt_entry(csid->formats, csid->nformats, + format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, input_format->code); num_bytes_per_line = input_format->width * format->bpp * format->spp / 8; num_lines = input_format->height; @@ -240,7 +91,8 @@ static void csid_configure_stream(struct csid_device *csid, u8 enable) struct csid_phy_config *phy = &csid->phy; input_format = &csid->fmt[MSM_CSID_PAD_SINK]; - format = csid_get_fmt_entry(csid->formats, csid->nformats, + format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, input_format->code); val = phy->lane_cnt - 1; @@ -387,8 +239,6 @@ static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code, static void csid_subdev_init(struct csid_device *csid) { - csid->formats = csid_formats; - csid->nformats = ARRAY_SIZE(csid_formats); csid->testgen.modes = csid_testgen_modes; csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN1; } diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen2.c b/drivers/media/platform/qcom/camss/camss-csid-gen2.c index b11de4797cca..e1c757933e27 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen2.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen2.c @@ -176,306 +176,171 @@ #define TPG_COLOR_BOX_CFG_MODE 0 #define TPG_COLOR_BOX_PATTERN_SEL 2 -static const struct csid_format csid_formats[] = { - { - MEDIA_BUS_FMT_UYVY8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_VYUY8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_YUYV8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_YVYU8_1X16, - DATA_TYPE_YUV422_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 2, - }, - { - MEDIA_BUS_FMT_SBGGR8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_SBGGR10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_Y8_1X8, - DATA_TYPE_RAW_8BIT, - DECODE_FORMAT_UNCOMPRESSED_8_BIT, - 8, - 1, - }, - { - MEDIA_BUS_FMT_Y10_1X10, - DATA_TYPE_RAW_10BIT, - DECODE_FORMAT_UNCOMPRESSED_10_BIT, - 10, - 1, - }, - { - MEDIA_BUS_FMT_SBGGR12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB12_1X12, - DATA_TYPE_RAW_12BIT, - DECODE_FORMAT_UNCOMPRESSED_12_BIT, - 12, - 1, - }, - { - MEDIA_BUS_FMT_SBGGR14_1X14, - DATA_TYPE_RAW_14BIT, - DECODE_FORMAT_UNCOMPRESSED_14_BIT, - 14, - 1, - }, - { - MEDIA_BUS_FMT_SGBRG14_1X14, - DATA_TYPE_RAW_14BIT, - DECODE_FORMAT_UNCOMPRESSED_14_BIT, - 14, - 1, - }, - { - MEDIA_BUS_FMT_SGRBG14_1X14, - DATA_TYPE_RAW_14BIT, - DECODE_FORMAT_UNCOMPRESSED_14_BIT, - 14, - 1, - }, - { - MEDIA_BUS_FMT_SRGGB14_1X14, - DATA_TYPE_RAW_14BIT, - DECODE_FORMAT_UNCOMPRESSED_14_BIT, - 14, - 1, - }, -}; - -static void __csid_configure_stream(struct csid_device *csid, u8 enable, u8 vc) +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy, int vc) { - struct csid_testgen_config *tg = &csid->testgen; - u32 val; - u32 phy_sel = 0; u8 lane_cnt = csid->phy.lane_cnt; - /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */ - struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc]; - const struct csid_format *format = csid_get_fmt_entry(csid->formats, csid->nformats, - input_format->code); + int val; if (!lane_cnt) lane_cnt = 4; - if (!tg->enabled) - phy_sel = csid->phy.csiphy_id; - - if (enable) { - /* - * DT_ID is a two bit bitfield that is concatenated with - * the four least significant bits of the five bit VC - * bitfield to generate an internal CID value. - * - * CSID_RDI_CFG0(vc) - * DT_ID : 28:27 - * VC : 26:22 - * DT : 21:16 - * - * CID : VC 3:0 << 2 | DT_ID 1:0 - */ - u8 dt_id = vc & 0x03; - - if (tg->enabled) { - /* configure one DT, infinite frames */ - val = vc << TPG_VC_CFG0_VC_NUM; - val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE; - val |= 0 << TPG_VC_CFG0_NUM_FRAMES; - writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0); - - val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT; - val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT; - writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1); - - writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED); - - val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT; - val |= (input_format->width & 0x1fff) << TPG_DT_n_CFG_0_FRAME_WIDTH; - writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0)); - - val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE; - writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0)); - - val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE; - val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD; - val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT; - writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0)); - - writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG); - - writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG); - } + val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; + val |= phy->csiphy_id << CSI2_RX_CFG0_PHY_NUM_SEL; + writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0); - val = 1 << RDI_CFG0_BYTE_CNTR_EN; - val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN; - val |= 1 << RDI_CFG0_TIMESTAMP_EN; - /* note: for non-RDI path, this should be format->decode_format */ - val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; - val |= format->data_type << RDI_CFG0_DATA_TYPE; - val |= vc << RDI_CFG0_VIRTUAL_CHANNEL; - val |= dt_id << RDI_CFG0_DT_ID; - writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); + val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN; + if (vc > 3) + val |= 1 << CSI2_RX_CFG1_VC_MODE; + val |= 1 << CSI2_RX_CFG1_MISR_EN; + writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1); +} - /* CSID_TIMESTAMP_STB_POST_IRQ */ - val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL; - writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc)); +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val; - val = 1; - writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc)); + if (enable) + val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD; + else + val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD; + writel_relaxed(val, csid->base + CSID_RDI_CTRL(rdi)); +} - val = 0; - writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc)); +static void __csid_configure_testgen(struct csid_device *csid, u8 enable, u8 vc) +{ + struct csid_testgen_config *tg = &csid->testgen; + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + u8 lane_cnt = csid->phy.lane_cnt; + u32 val; - val = 1; - writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc)); + if (!lane_cnt) + lane_cnt = 4; - val = 0; - writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc)); + /* configure one DT, infinite frames */ + val = vc << TPG_VC_CFG0_VC_NUM; + val |= INTELEAVING_MODE_ONE_SHOT << TPG_VC_CFG0_LINE_INTERLEAVING_MODE; + val |= 0 << TPG_VC_CFG0_NUM_FRAMES; + writel_relaxed(val, csid->base + CSID_TPG_VC_CFG0); - val = 1; - writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc)); + val = 0x740 << TPG_VC_CFG1_H_BLANKING_COUNT; + val |= 0x3ff << TPG_VC_CFG1_V_BLANKING_COUNT; + writel_relaxed(val, csid->base + CSID_TPG_VC_CFG1); - val = 0; - writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc)); + writel_relaxed(0x12345678, csid->base + CSID_TPG_LFSR_SEED); - val = 1; - writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc)); + val = (input_format->height & 0x1fff) << TPG_DT_n_CFG_0_FRAME_HEIGHT; + val |= (input_format->width & 0x1fff) << TPG_DT_n_CFG_0_FRAME_WIDTH; + writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_0(0)); - val = 0; - writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc)); + val = format->data_type << TPG_DT_n_CFG_1_DATA_TYPE; + writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_1(0)); - val = 0; - writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc)); + val = (tg->mode - 1) << TPG_DT_n_CFG_2_PAYLOAD_MODE; + val |= 0xBE << TPG_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD; + val |= format->decode_format << TPG_DT_n_CFG_2_ENCODE_FORMAT; + writel_relaxed(val, csid->base + CSID_TPG_DT_n_CFG_2(0)); - val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc)); - val |= 1 << RDI_CFG0_ENABLE; - writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); - } + writel_relaxed(0, csid->base + CSID_TPG_COLOR_BARS_CFG); - if (tg->enabled) { - val = enable << TPG_CTRL_TEST_EN; - val |= 1 << TPG_CTRL_FS_PKT_EN; - val |= 1 << TPG_CTRL_FE_PKT_EN; - val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES; - val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS; - val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES; - writel_relaxed(val, csid->base + CSID_TPG_CTRL); - } + writel_relaxed(0, csid->base + CSID_TPG_COLOR_BOX_CFG); - val = (lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; - val |= csid->phy.lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; - val |= phy_sel << CSI2_RX_CFG0_PHY_NUM_SEL; - writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0); + val = enable << TPG_CTRL_TEST_EN; + val |= 1 << TPG_CTRL_FS_PKT_EN; + val |= 1 << TPG_CTRL_FE_PKT_EN; + val |= (lane_cnt - 1) << TPG_CTRL_NUM_ACTIVE_LANES; + val |= 0x64 << TPG_CTRL_CYCLES_BETWEEN_PKTS; + val |= 0xA << TPG_CTRL_NUM_TRAIL_BYTES; + writel_relaxed(val, csid->base + CSID_TPG_CTRL); +} - val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN; - if (vc > 3) - val |= 1 << CSI2_RX_CFG1_VC_MODE; - val |= 1 << CSI2_RX_CFG1_MISR_EN; - writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG1); +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc) +{ + /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + u32 val; - if (enable) - val = HALT_CMD_RESUME_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD; - else - val = HALT_CMD_HALT_AT_FRAME_BOUNDARY << RDI_CTRL_HALT_CMD; + /* + * DT_ID is a two bit bitfield that is concatenated with + * the four least significant bits of the five bit VC + * bitfield to generate an internal CID value. + * + * CSID_RDI_CFG0(vc) + * DT_ID : 28:27 + * VC : 26:22 + * DT : 21:16 + * + * CID : VC 3:0 << 2 | DT_ID 1:0 + */ + u8 dt_id = vc & 0x03; + + val = 1 << RDI_CFG0_BYTE_CNTR_EN; + val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN; + val |= 1 << RDI_CFG0_TIMESTAMP_EN; + /* note: for non-RDI path, this should be format->decode_format */ + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= format->data_type << RDI_CFG0_DATA_TYPE; + val |= vc << RDI_CFG0_VIRTUAL_CHANNEL; + val |= dt_id << RDI_CFG0_DT_ID; + writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); + + /* CSID_TIMESTAMP_STB_POST_IRQ */ + val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL; + writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc)); + + val = 1; + writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc)); + + val = 0; + writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc)); + + val = 1; + writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc)); + + val = 0; + writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc)); + + val = 1; + writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc)); + + val = 0; + writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc)); + + val = 1; + writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc)); + + val = 0; + writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc)); + + val = 0; writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc)); + + val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc)); + val |= enable << RDI_CFG0_ENABLE; + writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc)); } static void csid_configure_stream(struct csid_device *csid, u8 enable) { + struct csid_testgen_config *tg = &csid->testgen; u8 i; /* Loop through all enabled VCs and configure stream for each */ for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) - if (csid->phy.en_vc & BIT(i)) - __csid_configure_stream(csid, enable, i); + if (csid->phy.en_vc & BIT(i)) { + if (tg->enabled) + __csid_configure_testgen(csid, enable, i); + + __csid_configure_rdi_stream(csid, enable, i); + __csid_configure_rx(csid, &csid->phy, i); + __csid_ctrl_rdi(csid, enable, i); + } } static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) @@ -612,8 +477,6 @@ static u32 csid_src_pad_code(struct csid_device *csid, u32 sink_code, static void csid_subdev_init(struct csid_device *csid) { - csid->formats = csid_formats; - csid->nformats = ARRAY_SIZE(csid_formats); csid->testgen.modes = csid_testgen_modes; csid->testgen.nmodes = CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2; } diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c index eb27d69e89a1..858db5d4ca75 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.c +++ b/drivers/media/platform/qcom/camss/camss-csid.c @@ -45,6 +45,450 @@ const char * const csid_testgen_modes[] = { NULL }; +static const struct csid_format_info formats_4_1[] = { + { + MEDIA_BUS_FMT_UYVY8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_VYUY8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_YUYV8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_YVYU8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_SBGGR8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SBGGR10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SBGGR12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_Y10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, +}; + +static const struct csid_format_info formats_4_7[] = { + { + MEDIA_BUS_FMT_UYVY8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_VYUY8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_YUYV8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_YVYU8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_SBGGR8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SBGGR10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SBGGR12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SBGGR14_1X14, + DATA_TYPE_RAW_14BIT, + DECODE_FORMAT_UNCOMPRESSED_14_BIT, + 14, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG14_1X14, + DATA_TYPE_RAW_14BIT, + DECODE_FORMAT_UNCOMPRESSED_14_BIT, + 14, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG14_1X14, + DATA_TYPE_RAW_14BIT, + DECODE_FORMAT_UNCOMPRESSED_14_BIT, + 14, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB14_1X14, + DATA_TYPE_RAW_14BIT, + DECODE_FORMAT_UNCOMPRESSED_14_BIT, + 14, + 1, + }, + { + MEDIA_BUS_FMT_Y10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, +}; + +static const struct csid_format_info formats_gen2[] = { + { + MEDIA_BUS_FMT_UYVY8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_VYUY8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_YUYV8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_YVYU8_1X16, + DATA_TYPE_YUV422_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 2, + }, + { + MEDIA_BUS_FMT_SBGGR8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_SBGGR10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_Y8_1X8, + DATA_TYPE_RAW_8BIT, + DECODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + 1, + }, + { + MEDIA_BUS_FMT_Y10_1X10, + DATA_TYPE_RAW_10BIT, + DECODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + 1, + }, + { + MEDIA_BUS_FMT_SBGGR12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB12_1X12, + DATA_TYPE_RAW_12BIT, + DECODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + 1, + }, + { + MEDIA_BUS_FMT_SBGGR14_1X14, + DATA_TYPE_RAW_14BIT, + DECODE_FORMAT_UNCOMPRESSED_14_BIT, + 14, + 1, + }, + { + MEDIA_BUS_FMT_SGBRG14_1X14, + DATA_TYPE_RAW_14BIT, + DECODE_FORMAT_UNCOMPRESSED_14_BIT, + 14, + 1, + }, + { + MEDIA_BUS_FMT_SGRBG14_1X14, + DATA_TYPE_RAW_14BIT, + DECODE_FORMAT_UNCOMPRESSED_14_BIT, + 14, + 1, + }, + { + MEDIA_BUS_FMT_SRGGB14_1X14, + DATA_TYPE_RAW_14BIT, + DECODE_FORMAT_UNCOMPRESSED_14_BIT, + 14, + 1, + }, +}; + +const struct csid_formats csid_formats_4_1 = { + .nformats = ARRAY_SIZE(formats_4_1), + .formats = formats_4_1 +}; + +const struct csid_formats csid_formats_4_7 = { + .nformats = ARRAY_SIZE(formats_4_7), + .formats = formats_4_7 +}; + +const struct csid_formats csid_formats_gen2 = { + .nformats = ARRAY_SIZE(formats_gen2), + .formats = formats_gen2 +}; + u32 csid_find_code(u32 *codes, unsigned int ncodes, unsigned int match_format_idx, u32 match_code) { @@ -65,9 +509,9 @@ u32 csid_find_code(u32 *codes, unsigned int ncodes, return codes[0]; } -const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats, - unsigned int nformats, - u32 code) +const struct csid_format_info *csid_get_fmt_entry(const struct csid_format_info *formats, + unsigned int nformats, + u32 code) { unsigned int i; @@ -87,12 +531,12 @@ const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats, static int csid_set_clock_rates(struct csid_device *csid) { struct device *dev = csid->camss->dev; - const struct csid_format *fmt; + const struct csid_format_info *fmt; s64 link_freq; int i, j; int ret; - fmt = csid_get_fmt_entry(csid->formats, csid->nformats, + fmt = csid_get_fmt_entry(csid->res->formats->formats, csid->res->formats->nformats, csid->fmt[MSM_CSIPHY_PAD_SINK].code); link_freq = camss_get_link_freq(&csid->subdev.entity, fmt->bpp, csid->phy.lane_cnt); @@ -158,7 +602,6 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) struct csid_device *csid = v4l2_get_subdevdata(sd); struct camss *camss = csid->camss; struct device *dev = camss->dev; - struct vfe_device *vfe = &camss->vfe[csid->id]; int ret = 0; if (on) { @@ -167,7 +610,7 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) * switching on the CSID. Do so unconditionally, as there is no * drawback in following the same powering order on older SoCs. */ - ret = vfe_get(vfe); + ret = csid->res->parent_dev_ops->get(camss, csid->id); if (ret < 0) return ret; @@ -202,7 +645,7 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) enable_irq(csid->irq); - ret = csid->ops->reset(csid); + ret = csid->res->hw_ops->reset(csid); if (ret < 0) { disable_irq(csid->irq); camss_disable_clocks(csid->nclocks, csid->clock); @@ -212,14 +655,14 @@ static int csid_set_power(struct v4l2_subdev *sd, int on) return ret; } - csid->ops->hw_version(csid); + csid->res->hw_ops->hw_version(csid); } else { disable_irq(csid->irq); camss_disable_clocks(csid->nclocks, csid->clock); regulator_bulk_disable(csid->num_supplies, csid->supplies); pm_runtime_put_sync(dev); - vfe_put(vfe); + csid->res->parent_dev_ops->put(camss, csid->id); } return ret; @@ -253,7 +696,7 @@ static int csid_set_stream(struct v4l2_subdev *sd, int enable) } if (csid->phy.need_vc_update) { - csid->ops->configure_stream(csid, enable); + csid->res->hw_ops->configure_stream(csid, enable); csid->phy.need_vc_update = false; } @@ -301,12 +744,12 @@ static void csid_try_format(struct csid_device *csid, case MSM_CSID_PAD_SINK: /* Set format on sink pad */ - for (i = 0; i < csid->nformats; i++) - if (fmt->code == csid->formats[i].code) + for (i = 0; i < csid->res->formats->nformats; i++) + if (fmt->code == csid->res->formats->formats[i].code) break; /* If not found, use UYVY as default */ - if (i >= csid->nformats) + if (i >= csid->res->formats->nformats) fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; fmt->width = clamp_t(u32, fmt->width, 1, 8191); @@ -325,17 +768,17 @@ static void csid_try_format(struct csid_device *csid, *fmt = *__csid_get_format(csid, sd_state, MSM_CSID_PAD_SINK, which); - fmt->code = csid->ops->src_pad_code(csid, fmt->code, 0, code); + fmt->code = csid->res->hw_ops->src_pad_code(csid, fmt->code, 0, code); } else { /* Test generator is enabled, set format on source */ /* pad to allow test generator usage */ - for (i = 0; i < csid->nformats; i++) - if (csid->formats[i].code == fmt->code) + for (i = 0; i < csid->res->formats->nformats; i++) + if (csid->res->formats->formats[i].code == fmt->code) break; /* If not found, use UYVY as default */ - if (i >= csid->nformats) + if (i >= csid->res->formats->nformats) fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; fmt->width = clamp_t(u32, fmt->width, 1, 8191); @@ -363,10 +806,10 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, struct csid_device *csid = v4l2_get_subdevdata(sd); if (code->pad == MSM_CSID_PAD_SINK) { - if (code->index >= csid->nformats) + if (code->index >= csid->res->formats->nformats) return -EINVAL; - code->code = csid->formats[code->index].code; + code->code = csid->res->formats->formats[code->index].code; } else { if (csid->testgen_mode->cur.val == 0) { struct v4l2_mbus_framefmt *sink_fmt; @@ -375,15 +818,15 @@ static int csid_enum_mbus_code(struct v4l2_subdev *sd, MSM_CSID_PAD_SINK, code->which); - code->code = csid->ops->src_pad_code(csid, sink_fmt->code, - code->index, 0); + code->code = csid->res->hw_ops->src_pad_code(csid, sink_fmt->code, + code->index, 0); if (!code->code) return -EINVAL; } else { - if (code->index >= csid->nformats) + if (code->index >= csid->res->formats->nformats) return -EINVAL; - code->code = csid->formats[code->index].code; + code->code = csid->res->formats->formats[code->index].code; } } @@ -529,7 +972,7 @@ static int csid_set_test_pattern(struct csid_device *csid, s32 value) tg->enabled = !!value; - return csid->ops->configure_testgen_pattern(csid, value); + return csid->res->hw_ops->configure_testgen_pattern(csid, value); } /* @@ -575,9 +1018,14 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, csid->camss = camss; csid->id = id; - csid->ops = res->ops; + csid->res = &res->csid; + + if (dev_WARN_ONCE(dev, !csid->res->parent_dev_ops, + "Error: CSID depends on VFE/IFE device ops!\n")) { + return -EINVAL; + } - csid->ops->subdev_init(csid); + csid->res->hw_ops->subdev_init(csid); /* Memory */ @@ -587,9 +1035,11 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, * VFE to be initialized before CSID */ if (id >= 2) /* VFE/CSID lite */ - csid->base = camss->vfe[id].base + VFE_480_LITE_CSID_OFFSET; + csid->base = csid->res->parent_dev_ops->get_base_address(camss, id) + + VFE_480_LITE_CSID_OFFSET; else - csid->base = camss->vfe[id].base + VFE_480_CSID_OFFSET; + csid->base = csid->res->parent_dev_ops->get_base_address(camss, id) + + VFE_480_CSID_OFFSET; } else { csid->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]); if (IS_ERR(csid->base)) @@ -605,7 +1055,7 @@ int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, csid->irq = ret; snprintf(csid->irq_name, sizeof(csid->irq_name), "%s_%s%d", dev_name(dev), MSM_CSID_NAME, csid->id); - ret = devm_request_irq(dev, csid->irq, csid->ops->isr, + ret = devm_request_irq(dev, csid->irq, csid->res->hw_ops->isr, IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN, csid->irq_name, csid); if (ret < 0) { @@ -899,5 +1349,5 @@ void msm_csid_unregister_entity(struct csid_device *csid) inline bool csid_is_lite(struct csid_device *csid) { - return csid->camss->res->csid_res[csid->id].is_lite; + return csid->camss->res->csid_res[csid->id].csid.is_lite; } diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index fddccb69da13..8cdae98e4dca 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -67,7 +67,7 @@ enum csid_testgen_mode { CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2 = 9, /* excluding disabled */ }; -struct csid_format { +struct csid_format_info { u32 code; u8 data_type; u8 decode_format; @@ -75,6 +75,11 @@ struct csid_format { u8 spp; /* bus samples per pixel */ }; +struct csid_formats { + unsigned int nformats; + const struct csid_format_info *formats; +}; + struct csid_testgen_config { enum csid_testgen_mode mode; const char * const*modes; @@ -149,6 +154,13 @@ struct csid_hw_ops { void (*subdev_init)(struct csid_device *csid); }; +struct csid_subdev_resources { + bool is_lite; + const struct csid_hw_ops *hw_ops; + const struct parent_dev_ops *parent_dev_ops; + const struct csid_formats *formats; +}; + struct csid_device { struct camss *camss; u8 id; @@ -167,9 +179,7 @@ struct csid_device { struct v4l2_mbus_framefmt fmt[MSM_CSID_PADS_NUM]; struct v4l2_ctrl_handler ctrls; struct v4l2_ctrl *testgen_mode; - const struct csid_format *formats; - unsigned int nformats; - const struct csid_hw_ops *ops; + const struct csid_subdev_resources *res; }; struct camss_subdev_resources; @@ -188,16 +198,16 @@ u32 csid_find_code(u32 *codes, unsigned int ncode, unsigned int match_format_idx, u32 match_code); /* - * csid_get_fmt_entry - Find csid_format entry with matching format code - * @formats: Array of format csid_format entries + * csid_get_fmt_entry - Find csid_format_info entry with matching format code + * @formats: Array of format csid_format_info entries * @nformats: Length of @nformats array * @code: Desired format code * * Return formats[0] on failure to find code */ -const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats, - unsigned int nformats, - u32 code); +const struct csid_format_info *csid_get_fmt_entry(const struct csid_format_info *formats, + unsigned int nformats, + u32 code); int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid, const struct camss_subdev_resources *res, u8 id); @@ -211,6 +221,10 @@ void msm_csid_get_csid_id(struct media_entity *entity, u8 *id); extern const char * const csid_testgen_modes[]; +extern const struct csid_formats csid_formats_4_1; +extern const struct csid_formats csid_formats_4_7; +extern const struct csid_formats csid_formats_gen2; + extern const struct csid_hw_ops csid_ops_4_1; extern const struct csid_hw_ops csid_ops_4_7; extern const struct csid_hw_ops csid_ops_gen2; diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index f50e2235c37f..f341f7b7fd8a 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -148,6 +148,91 @@ csiphy_reg_t lane_regs_sdm845[5][14] = { }, }; +/* GEN2 1.1 2PH */ +static const struct +csiphy_reg_t lane_regs_sc8280xp[5][14] = { + { + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x000C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0708, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0764, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0200, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0208, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x020C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, + { + {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0600, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0608, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x060C, 0x00, 0x00, CSIPHY_DNP_PARAMS}, + {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + }, +}; + /* GEN2 1.2.1 2PH */ static const struct csiphy_reg_t lane_regs_sm8250[5][20] = { @@ -420,14 +505,22 @@ static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy, u32 val; switch (csiphy->camss->res->version) { - case CAMSS_845: - r = &lane_regs_sdm845[0][0]; - array_size = ARRAY_SIZE(lane_regs_sdm845[0]); + case CAMSS_7280: + r = &lane_regs_sm8250[0][0]; + array_size = ARRAY_SIZE(lane_regs_sm8250[0]); break; case CAMSS_8250: r = &lane_regs_sm8250[0][0]; array_size = ARRAY_SIZE(lane_regs_sm8250[0]); break; + case CAMSS_8280XP: + r = &lane_regs_sc8280xp[0][0]; + array_size = ARRAY_SIZE(lane_regs_sc8280xp[0]); + break; + case CAMSS_845: + r = &lane_regs_sdm845[0][0]; + array_size = ARRAY_SIZE(lane_regs_sdm845[0]); + break; default: WARN(1, "unknown cspi version\n"); return; @@ -463,13 +556,27 @@ static u8 csiphy_get_lane_mask(struct csiphy_lanes_cfg *lane_cfg) return lane_mask; } +static bool csiphy_is_gen2(u32 version) +{ + bool ret = false; + + switch (version) { + case CAMSS_7280: + case CAMSS_8250: + case CAMSS_8280XP: + case CAMSS_845: + ret = true; + break; + } + + return ret; +} + static void csiphy_lanes_enable(struct csiphy_device *csiphy, struct csiphy_config *cfg, s64 link_freq, u8 lane_mask) { struct csiphy_lanes_cfg *c = &cfg->csi2->lane_cfg; - bool is_gen2 = (csiphy->camss->res->version == CAMSS_845 || - csiphy->camss->res->version == CAMSS_8250); u8 settle_cnt; u8 val; int i; @@ -491,7 +598,7 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, val = 0x00; writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(0)); - if (is_gen2) + if (csiphy_is_gen2(csiphy->camss->res->version)) csiphy_gen2_config_lanes(csiphy, settle_cnt); else csiphy_gen1_config_lanes(csiphy, cfg, settle_cnt); diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c index 264c99efeae8..3791c2d8a6cf 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c @@ -24,12 +24,7 @@ #define MSM_CSIPHY_NAME "msm_csiphy" -struct csiphy_format { - u32 code; - u8 bpp; -}; - -static const struct csiphy_format csiphy_formats_8x16[] = { +static const struct csiphy_format_info formats_8x16[] = { { MEDIA_BUS_FMT_UYVY8_1X16, 8 }, { MEDIA_BUS_FMT_VYUY8_1X16, 8 }, { MEDIA_BUS_FMT_YUYV8_1X16, 8 }, @@ -49,7 +44,7 @@ static const struct csiphy_format csiphy_formats_8x16[] = { { MEDIA_BUS_FMT_Y10_1X10, 10 }, }; -static const struct csiphy_format csiphy_formats_8x96[] = { +static const struct csiphy_format_info formats_8x96[] = { { MEDIA_BUS_FMT_UYVY8_1X16, 8 }, { MEDIA_BUS_FMT_VYUY8_1X16, 8 }, { MEDIA_BUS_FMT_YUYV8_1X16, 8 }, @@ -73,7 +68,7 @@ static const struct csiphy_format csiphy_formats_8x96[] = { { MEDIA_BUS_FMT_Y10_1X10, 10 }, }; -static const struct csiphy_format csiphy_formats_sdm845[] = { +static const struct csiphy_format_info formats_sdm845[] = { { MEDIA_BUS_FMT_UYVY8_1X16, 8 }, { MEDIA_BUS_FMT_VYUY8_1X16, 8 }, { MEDIA_BUS_FMT_YUYV8_1X16, 8 }, @@ -98,6 +93,26 @@ static const struct csiphy_format csiphy_formats_sdm845[] = { { MEDIA_BUS_FMT_Y10_1X10, 10 }, }; +const struct csiphy_formats csiphy_formats_8x16 = { + .nformats = ARRAY_SIZE(formats_8x16), + .formats = formats_8x16 +}; + +const struct csiphy_formats csiphy_formats_8x96 = { + .nformats = ARRAY_SIZE(formats_8x96), + .formats = formats_8x96 +}; + +const struct csiphy_formats csiphy_formats_sc7280 = { + .nformats = ARRAY_SIZE(formats_sdm845), + .formats = formats_sdm845 +}; + +const struct csiphy_formats csiphy_formats_sdm845 = { + .nformats = ARRAY_SIZE(formats_sdm845), + .formats = formats_sdm845 +}; + /* * csiphy_get_bpp - map media bus format to bits per pixel * @formats: supported media bus formats array @@ -106,7 +121,7 @@ static const struct csiphy_format csiphy_formats_sdm845[] = { * * Return number of bits per pixel */ -static u8 csiphy_get_bpp(const struct csiphy_format *formats, +static u8 csiphy_get_bpp(const struct csiphy_format_info *formats, unsigned int nformats, u32 code) { unsigned int i; @@ -131,7 +146,7 @@ static int csiphy_set_clock_rates(struct csiphy_device *csiphy) int i, j; int ret; - u8 bpp = csiphy_get_bpp(csiphy->formats, csiphy->nformats, + u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats, csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data; @@ -202,28 +217,41 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) if (ret < 0) return ret; + ret = regulator_bulk_enable(csiphy->num_supplies, + csiphy->supplies); + if (ret < 0) { + pm_runtime_put_sync(dev); + return ret; + } + ret = csiphy_set_clock_rates(csiphy); if (ret < 0) { + regulator_bulk_disable(csiphy->num_supplies, + csiphy->supplies); pm_runtime_put_sync(dev); return ret; } ret = camss_enable_clocks(csiphy->nclocks, csiphy->clock, dev); if (ret < 0) { + regulator_bulk_disable(csiphy->num_supplies, + csiphy->supplies); pm_runtime_put_sync(dev); return ret; } enable_irq(csiphy->irq); - csiphy->ops->reset(csiphy); + csiphy->res->hw_ops->reset(csiphy); - csiphy->ops->hw_version_read(csiphy, dev); + csiphy->res->hw_ops->hw_version_read(csiphy, dev); } else { disable_irq(csiphy->irq); camss_disable_clocks(csiphy->nclocks, csiphy->clock); + regulator_bulk_disable(csiphy->num_supplies, csiphy->supplies); + pm_runtime_put_sync(dev); } @@ -243,8 +271,8 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) { struct csiphy_config *cfg = &csiphy->cfg; s64 link_freq; - u8 lane_mask = csiphy->ops->get_lane_mask(&cfg->csi2->lane_cfg); - u8 bpp = csiphy_get_bpp(csiphy->formats, csiphy->nformats, + u8 lane_mask = csiphy->res->hw_ops->get_lane_mask(&cfg->csi2->lane_cfg); + u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats, csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data; u8 val; @@ -272,7 +300,7 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) wmb(); } - csiphy->ops->lanes_enable(csiphy, cfg, link_freq, lane_mask); + csiphy->res->hw_ops->lanes_enable(csiphy, cfg, link_freq, lane_mask); return 0; } @@ -285,7 +313,7 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) */ static void csiphy_stream_off(struct csiphy_device *csiphy) { - csiphy->ops->lanes_disable(csiphy, &csiphy->cfg); + csiphy->res->hw_ops->lanes_disable(csiphy, &csiphy->cfg); } @@ -350,12 +378,12 @@ static void csiphy_try_format(struct csiphy_device *csiphy, case MSM_CSIPHY_PAD_SINK: /* Set format on sink pad */ - for (i = 0; i < csiphy->nformats; i++) - if (fmt->code == csiphy->formats[i].code) + for (i = 0; i < csiphy->res->formats->nformats; i++) + if (fmt->code == csiphy->res->formats->formats[i].code) break; /* If not found, use UYVY as default */ - if (i >= csiphy->nformats) + if (i >= csiphy->res->formats->nformats) fmt->code = MEDIA_BUS_FMT_UYVY8_1X16; fmt->width = clamp_t(u32, fmt->width, 1, 8191); @@ -392,10 +420,10 @@ static int csiphy_enum_mbus_code(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *format; if (code->pad == MSM_CSIPHY_PAD_SINK) { - if (code->index >= csiphy->nformats) + if (code->index >= csiphy->res->formats->nformats) return -EINVAL; - code->code = csiphy->formats[code->index].code; + code->code = csiphy->res->formats->formats[code->index].code; } else { if (code->index > 0) return -EINVAL; @@ -564,24 +592,7 @@ int msm_csiphy_subdev_init(struct camss *camss, csiphy->camss = camss; csiphy->id = id; csiphy->cfg.combo_mode = 0; - csiphy->ops = res->ops; - - switch (camss->res->version) { - case CAMSS_8x16: - csiphy->formats = csiphy_formats_8x16; - csiphy->nformats = ARRAY_SIZE(csiphy_formats_8x16); - break; - case CAMSS_8x96: - case CAMSS_660: - csiphy->formats = csiphy_formats_8x96; - csiphy->nformats = ARRAY_SIZE(csiphy_formats_8x96); - break; - case CAMSS_845: - case CAMSS_8250: - csiphy->formats = csiphy_formats_sdm845; - csiphy->nformats = ARRAY_SIZE(csiphy_formats_sdm845); - break; - } + csiphy->res = &res->csiphy; /* Memory */ @@ -590,6 +601,7 @@ int msm_csiphy_subdev_init(struct camss *camss, return PTR_ERR(csiphy->base); if (camss->res->version == CAMSS_8x16 || + camss->res->version == CAMSS_8x53 || camss->res->version == CAMSS_8x96) { csiphy->base_clk_mux = devm_platform_ioremap_resource_byname(pdev, res->reg[1]); @@ -609,7 +621,7 @@ int msm_csiphy_subdev_init(struct camss *camss, snprintf(csiphy->irq_name, sizeof(csiphy->irq_name), "%s_%s%d", dev_name(dev), MSM_CSIPHY_NAME, csiphy->id); - ret = devm_request_irq(dev, csiphy->irq, csiphy->ops->isr, + ret = devm_request_irq(dev, csiphy->irq, csiphy->res->hw_ops->isr, IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN, csiphy->irq_name, csiphy); if (ret < 0) { @@ -683,7 +695,27 @@ int msm_csiphy_subdev_init(struct camss *camss, } } - return 0; + /* CSIPHY supplies */ + for (i = 0; i < ARRAY_SIZE(res->regulators); i++) { + if (res->regulators[i]) + csiphy->num_supplies++; + } + + if (csiphy->num_supplies) { + csiphy->supplies = devm_kmalloc_array(camss->dev, + csiphy->num_supplies, + sizeof(*csiphy->supplies), + GFP_KERNEL); + if (!csiphy->supplies) + return -ENOMEM; + } + + for (i = 0; i < csiphy->num_supplies; i++) + csiphy->supplies[i].supply = res->regulators[i]; + + ret = devm_regulator_bulk_get(camss->dev, csiphy->num_supplies, + csiphy->supplies); + return ret; } /* diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h index c9b7fe82b1f0..90cc3f976643 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.h +++ b/drivers/media/platform/qcom/camss/camss-csiphy.h @@ -26,6 +26,12 @@ struct csiphy_lane { u8 pol; }; +/** + * struct csiphy_lanes_cfg - CSIPHY lanes configuration + * @num_data: number of data lanes + * @data: data lanes configuration + * @clk: clock lane configuration (only for D-PHY) + */ struct csiphy_lanes_cfg { int num_data; struct csiphy_lane *data; @@ -42,6 +48,16 @@ struct csiphy_config { struct csiphy_csi2_cfg *csi2; }; +struct csiphy_format_info { + u32 code; + u8 bpp; +}; + +struct csiphy_formats { + unsigned int nformats; + const struct csiphy_format_info *formats; +}; + struct csiphy_device; struct csiphy_hw_ops { @@ -63,6 +79,11 @@ struct csiphy_hw_ops { irqreturn_t (*isr)(int irq, void *dev); }; +struct csiphy_subdev_resources { + const struct csiphy_hw_ops *hw_ops; + const struct csiphy_formats *formats; +}; + struct csiphy_device { struct camss *camss; u8 id; @@ -76,11 +97,11 @@ struct csiphy_device { bool *rate_set; int nclocks; u32 timer_clk_rate; + struct regulator_bulk_data *supplies; + int num_supplies; struct csiphy_config cfg; struct v4l2_mbus_framefmt fmt[MSM_CSIPHY_PADS_NUM]; - const struct csiphy_hw_ops *ops; - const struct csiphy_format *formats; - unsigned int nformats; + const struct csiphy_subdev_resources *res; }; struct camss_subdev_resources; @@ -94,6 +115,11 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, void msm_csiphy_unregister_entity(struct csiphy_device *csiphy); +extern const struct csiphy_formats csiphy_formats_8x16; +extern const struct csiphy_formats csiphy_formats_8x96; +extern const struct csiphy_formats csiphy_formats_sc7280; +extern const struct csiphy_formats csiphy_formats_sdm845; + extern const struct csiphy_hw_ops csiphy_ops_2ph_1_0; extern const struct csiphy_hw_ops csiphy_ops_3ph_1_0; diff --git a/drivers/media/platform/qcom/camss/camss-format.c b/drivers/media/platform/qcom/camss/camss-format.c new file mode 100644 index 000000000000..4a3d5549615c --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-format.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-format.c + * + * Qualcomm MSM Camera Subsystem - Format helpers + * + * Copyright (c) 2023, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Technologies, Inc. + */ +#include <linux/bug.h> +#include <linux/errno.h> + +#include "camss-format.h" + +/* + * camss_format_get_bpp - Map media bus format to bits per pixel + * @formats: supported media bus formats array + * @nformats: size of @formats array + * @code: media bus format code + * + * Return number of bits per pixel + */ +u8 camss_format_get_bpp(const struct camss_format_info *formats, unsigned int nformats, u32 code) +{ + unsigned int i; + + for (i = 0; i < nformats; i++) + if (code == formats[i].code) + return formats[i].mbus_bpp; + + WARN(1, "Unknown format\n"); + + return formats[0].mbus_bpp; +} + +/* + * camss_format_find_code - Find a format code in an array + * @code: a pointer to media bus format codes array + * @n_code: size of @code array + * @index: index of code in the array + * @req_code: required code + * + * Return media bus format code + */ +u32 camss_format_find_code(u32 *code, unsigned int n_code, unsigned int index, u32 req_code) +{ + unsigned int i; + + if (!req_code && index >= n_code) + return 0; + + for (i = 0; i < n_code; i++) { + if (req_code) { + if (req_code == code[i]) + return req_code; + } else { + if (i == index) + return code[i]; + } + } + + return code[0]; +} + +/* + * camss_format_find_format - Find a format in an array + * @code: media bus format code + * @pixelformat: V4L2 pixel format FCC identifier + * @formats: a pointer to formats array + * @nformats: size of @formats array + * + * Return index of a format or a negative error code otherwise + */ +int camss_format_find_format(u32 code, u32 pixelformat, const struct camss_format_info *formats, + unsigned int nformats) +{ + unsigned int i; + + for (i = 0; i < nformats; i++) { + if (formats[i].code == code && + formats[i].pixelformat == pixelformat) + return i; + } + + for (i = 0; i < nformats; i++) { + if (formats[i].code == code) + return i; + } + + return -EINVAL; +} diff --git a/drivers/media/platform/qcom/camss/camss-format.h b/drivers/media/platform/qcom/camss/camss-format.h new file mode 100644 index 000000000000..923a48c9c3fb --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-format.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * camss-format.h + * + * Qualcomm MSM Camera Subsystem - Format helpers + * + * Copyright (c) 2023, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Technologies, Inc. + */ +#ifndef __CAMSS_FORMAT_H__ +#define __CAMSS_FORMAT_H__ + +#include <linux/types.h> + +#define PER_PLANE_DATA(plane, h_fract_num, h_fract_den, v_fract_num, v_fract_den, _bpp) \ + .hsub[(plane)].numerator = (h_fract_num), \ + .hsub[(plane)].denominator = (h_fract_den), \ + .vsub[(plane)].numerator = (v_fract_num), \ + .vsub[(plane)].denominator = (v_fract_den), \ + .bpp[(plane)] = (_bpp) + +/* + * struct fract - Represents a fraction + * @numerator: Store the numerator part of the fraction + * @denominator: Store the denominator part of the fraction + */ +struct fract { + u8 numerator; + u8 denominator; +}; + +/* + * struct camss_format_info - ISP media bus format information + * @code: V4L2 media bus format code + * @mbus_bpp: Media bus bits per pixel + * @pixelformat: V4L2 pixel format FCC identifier + * @planes: Number of planes + * @hsub: Horizontal subsampling (for each plane) + * @vsub: Vertical subsampling (for each plane) + * @bpp: Bits per pixel when stored in memory (for each plane) + */ +struct camss_format_info { + u32 code; + u32 mbus_bpp; + u32 pixelformat; + u8 planes; + struct fract hsub[3]; + struct fract vsub[3]; + unsigned int bpp[3]; +}; + +struct camss_formats { + unsigned int nformats; + const struct camss_format_info *formats; +}; + +u8 camss_format_get_bpp(const struct camss_format_info *formats, unsigned int nformats, u32 code); +u32 camss_format_find_code(u32 *code, unsigned int n_code, unsigned int index, u32 req_code); +int camss_format_find_format(u32 code, u32 pixelformat, const struct camss_format_info *formats, + unsigned int nformats); + +#endif /* __CAMSS_FORMAT_H__ */ diff --git a/drivers/media/platform/qcom/camss/camss-ispif.c b/drivers/media/platform/qcom/camss/camss-ispif.c index a12dcc7ff438..2dc585c6123d 100644 --- a/drivers/media/platform/qcom/camss/camss-ispif.c +++ b/drivers/media/platform/qcom/camss/camss-ispif.c @@ -830,6 +830,7 @@ static int ispif_set_stream(struct v4l2_subdev *sd, int enable) ispif_select_cid(ispif, intf, cid, vfe, 1); ispif_config_irq(ispif, intf, vfe, 1); if (camss->res->version == CAMSS_8x96 || + camss->res->version == CAMSS_8x53 || camss->res->version == CAMSS_660) ispif_config_pack(ispif, line->fmt[MSM_ISPIF_PAD_SINK].code, @@ -848,6 +849,7 @@ static int ispif_set_stream(struct v4l2_subdev *sd, int enable) mutex_lock(&ispif->config_lock); if (camss->res->version == CAMSS_8x96 || + camss->res->version == CAMSS_8x53 || camss->res->version == CAMSS_660) ispif_config_pack(ispif, line->fmt[MSM_ISPIF_PAD_SINK].code, @@ -1111,6 +1113,7 @@ int msm_ispif_subdev_init(struct camss *camss, if (camss->res->version == CAMSS_8x16) ispif->line_num = 2; else if (camss->res->version == CAMSS_8x96 || + camss->res->version == CAMSS_8x53 || camss->res->version == CAMSS_660) ispif->line_num = 4; else @@ -1130,6 +1133,7 @@ int msm_ispif_subdev_init(struct camss *camss, ispif->line[i].nformats = ARRAY_SIZE(ispif_formats_8x16); } else if (camss->res->version == CAMSS_8x96 || + camss->res->version == CAMSS_8x53 || camss->res->version == CAMSS_660) { ispif->line[i].formats = ispif_formats_8x96; ispif->line[i].nformats = @@ -1162,6 +1166,7 @@ int msm_ispif_subdev_init(struct camss *camss, ret = devm_request_irq(dev, ispif->irq, ispif_isr_8x16, IRQF_TRIGGER_RISING, ispif->irq_name, ispif); else if (camss->res->version == CAMSS_8x96 || + camss->res->version == CAMSS_8x53 || camss->res->version == CAMSS_660) ret = devm_request_irq(dev, ispif->irq, ispif_isr_8x96, IRQF_TRIGGER_RISING, ispif->irq_name, ispif); diff --git a/drivers/media/platform/qcom/camss/camss-vfe-170.c b/drivers/media/platform/qcom/camss/camss-vfe-17x.c index 795ac3815339..380c99321030 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-170.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-17x.c @@ -353,7 +353,7 @@ static irqreturn_t vfe_isr(int irq, void *dev) writel_relaxed(status0, vfe->base + VFE_IRQ_CLEAR_0); writel_relaxed(status1, vfe->base + VFE_IRQ_CLEAR_1); - for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) { + for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) { vfe_bus_status[i] = readl_relaxed(vfe->base + VFE_BUS_IRQ_STATUS(i)); writel_relaxed(vfe_bus_status[i], vfe->base + VFE_BUS_IRQ_CLEAR(i)); } @@ -367,11 +367,11 @@ static irqreturn_t vfe_isr(int irq, void *dev) if (status0 & STATUS_0_RESET_ACK) vfe->isr_ops.reset_ack(vfe); - for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) + for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) if (status0 & STATUS_0_RDI_REG_UPDATE(i)) vfe->isr_ops.reg_update(vfe, i); - for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) + for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) if (status0 & STATUS_1_RDI_SOF(i)) vfe->isr_ops.sof(vfe, i); @@ -442,7 +442,7 @@ static int vfe_enable_output(struct vfe_line *line) { struct vfe_device *vfe = to_vfe(line); struct vfe_output *output = &line->output; - const struct vfe_hw_ops *ops = vfe->ops; + const struct vfe_hw_ops *ops = vfe->res->hw_ops; struct media_entity *sensor; unsigned long flags; unsigned int frame_skip = 0; @@ -560,7 +560,7 @@ static void vfe_isr_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) unsigned long flags; spin_lock_irqsave(&vfe->output_lock, flags); - vfe->ops->reg_update_clear(vfe, line_id); + vfe->res->hw_ops->reg_update_clear(vfe, line_id); output = &vfe->line[line_id].output; diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-1.c b/drivers/media/platform/qcom/camss/camss-vfe-4-1.c index ef6b34c915df..9a9007c3ff33 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-4-1.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-4-1.c @@ -892,7 +892,7 @@ static irqreturn_t vfe_isr(int irq, void *dev) u32 value0, value1; int i, j; - vfe->ops->isr_read(vfe, &value0, &value1); + vfe->res->hw_ops->isr_read(vfe, &value0, &value1); dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n", value0, value1); @@ -901,7 +901,7 @@ static irqreturn_t vfe_isr(int irq, void *dev) vfe->isr_ops.reset_ack(vfe); if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION) - vfe->ops->violation_read(vfe); + vfe->res->hw_ops->violation_read(vfe); if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK) vfe->isr_ops.halt_ack(vfe); @@ -938,7 +938,10 @@ static irqreturn_t vfe_isr(int irq, void *dev) */ static void vfe_4_1_pm_domain_off(struct vfe_device *vfe) { - /* nop */ + if (!vfe->res->has_pd) + return; + + vfe_pm_domain_off(vfe); } /* @@ -947,7 +950,10 @@ static void vfe_4_1_pm_domain_off(struct vfe_device *vfe) */ static int vfe_4_1_pm_domain_on(struct vfe_device *vfe) { - return 0; + if (!vfe->res->has_pd) + return 0; + + return vfe_pm_domain_on(vfe); } static const struct vfe_hw_ops_gen1 vfe_ops_gen1_4_1 = { diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-7.c b/drivers/media/platform/qcom/camss/camss-vfe-4-7.c index 7655d22a9fda..ce0719106bd3 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-4-7.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-4-7.c @@ -1050,7 +1050,7 @@ static irqreturn_t vfe_isr(int irq, void *dev) u32 value0, value1; int i, j; - vfe->ops->isr_read(vfe, &value0, &value1); + vfe->res->hw_ops->isr_read(vfe, &value0, &value1); dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n", value0, value1); @@ -1059,12 +1059,12 @@ static irqreturn_t vfe_isr(int irq, void *dev) vfe->isr_ops.reset_ack(vfe); if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION) - vfe->ops->violation_read(vfe); + vfe->res->hw_ops->violation_read(vfe); if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK) vfe->isr_ops.halt_ack(vfe); - for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) + for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i)) vfe->isr_ops.reg_update(vfe, i); diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-8.c b/drivers/media/platform/qcom/camss/camss-vfe-4-8.c index f52fa30f3853..6b59c8107a3c 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-4-8.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-4-8.c @@ -980,7 +980,7 @@ static irqreturn_t vfe_isr(int irq, void *dev) u32 value0, value1; int i, j; - vfe->ops->isr_read(vfe, &value0, &value1); + vfe->res->hw_ops->isr_read(vfe, &value0, &value1); dev_dbg(vfe->camss->dev, "VFE: status0 = 0x%08x, status1 = 0x%08x\n", value0, value1); @@ -989,12 +989,12 @@ static irqreturn_t vfe_isr(int irq, void *dev) vfe->isr_ops.reset_ack(vfe); if (value1 & VFE_0_IRQ_STATUS_1_VIOLATION) - vfe->ops->violation_read(vfe); + vfe->res->hw_ops->violation_read(vfe); if (value1 & VFE_0_IRQ_STATUS_1_BUS_BDG_HALT_ACK) vfe->isr_ops.halt_ack(vfe); - for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) + for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) if (value0 & VFE_0_IRQ_STATUS_0_line_n_REG_UPDATE(i)) vfe->isr_ops.reg_update(vfe, i); diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen1.c b/drivers/media/platform/qcom/camss/camss-vfe-gen1.c index 239d3d4ac666..eb33c03df27e 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-gen1.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen1.c @@ -37,7 +37,7 @@ static int vfe_disable_output(struct vfe_line *line) { struct vfe_device *vfe = to_vfe(line); struct vfe_output *output = &line->output; - const struct vfe_hw_ops *ops = vfe->ops; + const struct vfe_hw_ops *ops = vfe->res->hw_ops; unsigned long flags; unsigned long time; unsigned int i; @@ -162,14 +162,14 @@ static void vfe_output_frame_drop(struct vfe_device *vfe, vfe->ops_gen1->wm_set_framedrop_pattern(vfe, output->wm_idx[i], drop_pattern); } - vfe->ops->reg_update(vfe, container_of(output, struct vfe_line, output)->id); + vfe->res->hw_ops->reg_update(vfe, container_of(output, struct vfe_line, output)->id); } static int vfe_enable_output(struct vfe_line *line) { struct vfe_device *vfe = to_vfe(line); struct vfe_output *output = &line->output; - const struct vfe_hw_ops *ops = vfe->ops; + const struct vfe_hw_ops *ops = vfe->res->hw_ops; struct media_entity *sensor; unsigned long flags; unsigned int frame_skip = 0; @@ -545,7 +545,7 @@ static void vfe_isr_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) unsigned long flags; spin_lock_irqsave(&vfe->output_lock, flags); - vfe->ops->reg_update_clear(vfe, line_id); + vfe->res->hw_ops->reg_update_clear(vfe, line_id); output = &line->output; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 2062be668f49..95f6a1ac7eaf 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -32,139 +32,251 @@ #define SCALER_RATIO_MAX 16 -struct vfe_format { - u32 code; - u8 bpp; +static const struct camss_format_info formats_rdi_8x16[] = { + { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, }; -static const struct vfe_format formats_rdi_8x16[] = { - { MEDIA_BUS_FMT_UYVY8_1X16, 8 }, - { MEDIA_BUS_FMT_VYUY8_1X16, 8 }, - { MEDIA_BUS_FMT_YUYV8_1X16, 8 }, - { MEDIA_BUS_FMT_YVYU8_1X16, 8 }, - { MEDIA_BUS_FMT_SBGGR8_1X8, 8 }, - { MEDIA_BUS_FMT_SGBRG8_1X8, 8 }, - { MEDIA_BUS_FMT_SGRBG8_1X8, 8 }, - { MEDIA_BUS_FMT_SRGGB8_1X8, 8 }, - { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, - { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, - { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, - { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, - { MEDIA_BUS_FMT_SBGGR12_1X12, 12 }, - { MEDIA_BUS_FMT_SGBRG12_1X12, 12 }, - { MEDIA_BUS_FMT_SGRBG12_1X12, 12 }, - { MEDIA_BUS_FMT_SRGGB12_1X12, 12 }, - { MEDIA_BUS_FMT_Y10_1X10, 10 }, +static const struct camss_format_info formats_rdi_8x96[] = { + { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_SBGGR10, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SBGGR14_1X14, 14, V4L2_PIX_FMT_SBGGR14P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, + { MEDIA_BUS_FMT_SGBRG14_1X14, 14, V4L2_PIX_FMT_SGBRG14P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, + { MEDIA_BUS_FMT_SGRBG14_1X14, 14, V4L2_PIX_FMT_SGRBG14P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, + { MEDIA_BUS_FMT_SRGGB14_1X14, 14, V4L2_PIX_FMT_SRGGB14P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, + { MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_Y10, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, }; -static const struct vfe_format formats_pix_8x16[] = { - { MEDIA_BUS_FMT_UYVY8_1X16, 8 }, - { MEDIA_BUS_FMT_VYUY8_1X16, 8 }, - { MEDIA_BUS_FMT_YUYV8_1X16, 8 }, - { MEDIA_BUS_FMT_YVYU8_1X16, 8 }, +static const struct camss_format_info formats_rdi_845[] = { + { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_SBGGR8_1X8, 8, V4L2_PIX_FMT_SBGGR8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SGBRG8_1X8, 8, V4L2_PIX_FMT_SGBRG8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SGRBG8_1X8, 8, V4L2_PIX_FMT_SGRBG8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SRGGB8_1X8, 8, V4L2_PIX_FMT_SRGGB8, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_SBGGR10_1X10, 10, V4L2_PIX_FMT_SBGGR10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SGBRG10_1X10, 10, V4L2_PIX_FMT_SGBRG10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SGRBG10_1X10, 10, V4L2_PIX_FMT_SGRBG10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SRGGB10_1X10, 10, V4L2_PIX_FMT_SRGGB10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_SBGGR10, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_SBGGR12_1X12, 12, V4L2_PIX_FMT_SBGGR12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SGBRG12_1X12, 12, V4L2_PIX_FMT_SGBRG12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SGRBG12_1X12, 12, V4L2_PIX_FMT_SGRBG12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SRGGB12_1X12, 12, V4L2_PIX_FMT_SRGGB12P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 12) }, + { MEDIA_BUS_FMT_SBGGR14_1X14, 14, V4L2_PIX_FMT_SBGGR14P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, + { MEDIA_BUS_FMT_SGBRG14_1X14, 14, V4L2_PIX_FMT_SGBRG14P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, + { MEDIA_BUS_FMT_SGRBG14_1X14, 14, V4L2_PIX_FMT_SGRBG14P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, + { MEDIA_BUS_FMT_SRGGB14_1X14, 14, V4L2_PIX_FMT_SRGGB14P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 14) }, + { MEDIA_BUS_FMT_Y8_1X8, 8, V4L2_PIX_FMT_GREY, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 8) }, + { MEDIA_BUS_FMT_Y10_1X10, 10, V4L2_PIX_FMT_Y10P, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 10) }, + { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16, V4L2_PIX_FMT_Y10, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, }; -static const struct vfe_format formats_rdi_8x96[] = { - { MEDIA_BUS_FMT_UYVY8_1X16, 8 }, - { MEDIA_BUS_FMT_VYUY8_1X16, 8 }, - { MEDIA_BUS_FMT_YUYV8_1X16, 8 }, - { MEDIA_BUS_FMT_YVYU8_1X16, 8 }, - { MEDIA_BUS_FMT_SBGGR8_1X8, 8 }, - { MEDIA_BUS_FMT_SGBRG8_1X8, 8 }, - { MEDIA_BUS_FMT_SGRBG8_1X8, 8 }, - { MEDIA_BUS_FMT_SRGGB8_1X8, 8 }, - { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, - { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, - { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, - { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, - { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16 }, - { MEDIA_BUS_FMT_SBGGR12_1X12, 12 }, - { MEDIA_BUS_FMT_SGBRG12_1X12, 12 }, - { MEDIA_BUS_FMT_SGRBG12_1X12, 12 }, - { MEDIA_BUS_FMT_SRGGB12_1X12, 12 }, - { MEDIA_BUS_FMT_SBGGR14_1X14, 14 }, - { MEDIA_BUS_FMT_SGBRG14_1X14, 14 }, - { MEDIA_BUS_FMT_SGRBG14_1X14, 14 }, - { MEDIA_BUS_FMT_SRGGB14_1X14, 14 }, - { MEDIA_BUS_FMT_Y10_1X10, 10 }, - { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16 }, +static const struct camss_format_info formats_pix_8x16[] = { + { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV16, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV16, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV16, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV16, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV61, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV61, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV61, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV61, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, }; -static const struct vfe_format formats_pix_8x96[] = { - { MEDIA_BUS_FMT_UYVY8_1X16, 8 }, - { MEDIA_BUS_FMT_VYUY8_1X16, 8 }, - { MEDIA_BUS_FMT_YUYV8_1X16, 8 }, - { MEDIA_BUS_FMT_YVYU8_1X16, 8 }, +static const struct camss_format_info formats_pix_8x96[] = { + { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV12, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_YUYV8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_YVYU8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_UYVY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_VYUY8_1_5X8, 8, V4L2_PIX_FMT_NV21, 1, + PER_PLANE_DATA(0, 1, 1, 2, 3, 8) }, + { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV16, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV16, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV16, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV16, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_NV61, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_NV61, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_NV61, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_NV61, 1, + PER_PLANE_DATA(0, 1, 1, 1, 2, 8) }, + { MEDIA_BUS_FMT_UYVY8_1X16, 8, V4L2_PIX_FMT_UYVY, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_VYUY8_1X16, 8, V4L2_PIX_FMT_VYUY, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_YUYV8_1X16, 8, V4L2_PIX_FMT_YUYV, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, + { MEDIA_BUS_FMT_YVYU8_1X16, 8, V4L2_PIX_FMT_YVYU, 1, + PER_PLANE_DATA(0, 1, 1, 1, 1, 16) }, }; -static const struct vfe_format formats_rdi_845[] = { - { MEDIA_BUS_FMT_UYVY8_1X16, 8 }, - { MEDIA_BUS_FMT_VYUY8_1X16, 8 }, - { MEDIA_BUS_FMT_YUYV8_1X16, 8 }, - { MEDIA_BUS_FMT_YVYU8_1X16, 8 }, - { MEDIA_BUS_FMT_SBGGR8_1X8, 8 }, - { MEDIA_BUS_FMT_SGBRG8_1X8, 8 }, - { MEDIA_BUS_FMT_SGRBG8_1X8, 8 }, - { MEDIA_BUS_FMT_SRGGB8_1X8, 8 }, - { MEDIA_BUS_FMT_SBGGR10_1X10, 10 }, - { MEDIA_BUS_FMT_SGBRG10_1X10, 10 }, - { MEDIA_BUS_FMT_SGRBG10_1X10, 10 }, - { MEDIA_BUS_FMT_SRGGB10_1X10, 10 }, - { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, 16 }, - { MEDIA_BUS_FMT_SBGGR12_1X12, 12 }, - { MEDIA_BUS_FMT_SGBRG12_1X12, 12 }, - { MEDIA_BUS_FMT_SGRBG12_1X12, 12 }, - { MEDIA_BUS_FMT_SRGGB12_1X12, 12 }, - { MEDIA_BUS_FMT_SBGGR14_1X14, 14 }, - { MEDIA_BUS_FMT_SGBRG14_1X14, 14 }, - { MEDIA_BUS_FMT_SGRBG14_1X14, 14 }, - { MEDIA_BUS_FMT_SRGGB14_1X14, 14 }, - { MEDIA_BUS_FMT_Y8_1X8, 8 }, - { MEDIA_BUS_FMT_Y10_1X10, 10 }, - { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, 16 }, +const struct camss_formats vfe_formats_rdi_8x16 = { + .nformats = ARRAY_SIZE(formats_rdi_8x16), + .formats = formats_rdi_8x16 }; -/* - * vfe_get_bpp - map media bus format to bits per pixel - * @formats: supported media bus formats array - * @nformats: size of @formats array - * @code: media bus format code - * - * Return number of bits per pixel - */ -static u8 vfe_get_bpp(const struct vfe_format *formats, - unsigned int nformats, u32 code) -{ - unsigned int i; - - for (i = 0; i < nformats; i++) - if (code == formats[i].code) - return formats[i].bpp; - - WARN(1, "Unknown format\n"); - - return formats[0].bpp; -} +const struct camss_formats vfe_formats_pix_8x16 = { + .nformats = ARRAY_SIZE(formats_pix_8x16), + .formats = formats_pix_8x16 +}; -static u32 vfe_find_code(u32 *code, unsigned int n_code, - unsigned int index, u32 req_code) -{ - int i; +const struct camss_formats vfe_formats_rdi_8x96 = { + .nformats = ARRAY_SIZE(formats_rdi_8x96), + .formats = formats_rdi_8x96 +}; - if (!req_code && (index >= n_code)) - return 0; +const struct camss_formats vfe_formats_pix_8x96 = { + .nformats = ARRAY_SIZE(formats_pix_8x96), + .formats = formats_pix_8x96 +}; - for (i = 0; i < n_code; i++) - if (req_code) { - if (req_code == code[i]) - return req_code; - } else { - if (i == index) - return code[i]; - } +const struct camss_formats vfe_formats_rdi_845 = { + .nformats = ARRAY_SIZE(formats_rdi_845), + .formats = formats_rdi_845 +}; - return code[0]; -} +/* TODO: Replace with pix formats */ +const struct camss_formats vfe_formats_pix_845 = { + .nformats = ARRAY_SIZE(formats_rdi_845), + .formats = formats_rdi_845 +}; static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, unsigned int index, u32 src_req_code) @@ -173,6 +285,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, switch (vfe->camss->res->version) { case CAMSS_8x16: + case CAMSS_8x53: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: { @@ -181,8 +294,8 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, MEDIA_BUS_FMT_YUYV8_1_5X8, }; - return vfe_find_code(src_code, ARRAY_SIZE(src_code), - index, src_req_code); + return camss_format_find_code(src_code, ARRAY_SIZE(src_code), + index, src_req_code); } case MEDIA_BUS_FMT_YVYU8_1X16: { @@ -191,8 +304,8 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, MEDIA_BUS_FMT_YVYU8_1_5X8, }; - return vfe_find_code(src_code, ARRAY_SIZE(src_code), - index, src_req_code); + return camss_format_find_code(src_code, ARRAY_SIZE(src_code), + index, src_req_code); } case MEDIA_BUS_FMT_UYVY8_1X16: { @@ -201,8 +314,8 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, MEDIA_BUS_FMT_UYVY8_1_5X8, }; - return vfe_find_code(src_code, ARRAY_SIZE(src_code), - index, src_req_code); + return camss_format_find_code(src_code, ARRAY_SIZE(src_code), + index, src_req_code); } case MEDIA_BUS_FMT_VYUY8_1X16: { @@ -211,8 +324,8 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, MEDIA_BUS_FMT_VYUY8_1_5X8, }; - return vfe_find_code(src_code, ARRAY_SIZE(src_code), - index, src_req_code); + return camss_format_find_code(src_code, ARRAY_SIZE(src_code), + index, src_req_code); } default: if (index > 0) @@ -221,10 +334,12 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, return sink_code; } break; - case CAMSS_8x96: case CAMSS_660: - case CAMSS_845: + case CAMSS_7280: + case CAMSS_8x96: case CAMSS_8250: + case CAMSS_8280XP: + case CAMSS_845: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: { @@ -236,8 +351,8 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, MEDIA_BUS_FMT_YUYV8_1_5X8, }; - return vfe_find_code(src_code, ARRAY_SIZE(src_code), - index, src_req_code); + return camss_format_find_code(src_code, ARRAY_SIZE(src_code), + index, src_req_code); } case MEDIA_BUS_FMT_YVYU8_1X16: { @@ -249,8 +364,8 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, MEDIA_BUS_FMT_YVYU8_1_5X8, }; - return vfe_find_code(src_code, ARRAY_SIZE(src_code), - index, src_req_code); + return camss_format_find_code(src_code, ARRAY_SIZE(src_code), + index, src_req_code); } case MEDIA_BUS_FMT_UYVY8_1X16: { @@ -262,8 +377,8 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, MEDIA_BUS_FMT_UYVY8_1_5X8, }; - return vfe_find_code(src_code, ARRAY_SIZE(src_code), - index, src_req_code); + return camss_format_find_code(src_code, ARRAY_SIZE(src_code), + index, src_req_code); } case MEDIA_BUS_FMT_VYUY8_1X16: { @@ -275,8 +390,8 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, MEDIA_BUS_FMT_VYUY8_1_5X8, }; - return vfe_find_code(src_code, ARRAY_SIZE(src_code), - index, src_req_code); + return camss_format_find_code(src_code, ARRAY_SIZE(src_code), + index, src_req_code); } default: if (index > 0) @@ -295,7 +410,7 @@ int vfe_reset(struct vfe_device *vfe) reinit_completion(&vfe->reset_complete); - vfe->ops->global_reset(vfe); + vfe->res->hw_ops->global_reset(vfe); time = wait_for_completion_timeout(&vfe->reset_complete, msecs_to_jiffies(VFE_RESET_TIMEOUT_MS)); @@ -311,7 +426,7 @@ static void vfe_init_outputs(struct vfe_device *vfe) { int i; - for (i = 0; i < vfe->line_num; i++) { + for (i = 0; i < vfe->res->line_num; i++) { struct vfe_output *output = &vfe->line[i].output; output->state = VFE_OUTPUT_OFF; @@ -420,7 +535,7 @@ static int vfe_disable_output(struct vfe_line *line) spin_lock_irqsave(&vfe->output_lock, flags); for (i = 0; i < output->wm_num; i++) - vfe->ops->vfe_wm_stop(vfe, output->wm_idx[i]); + vfe->res->hw_ops->vfe_wm_stop(vfe, output->wm_idx[i]); output->gen2.active_num = 0; spin_unlock_irqrestore(&vfe->output_lock, flags); @@ -536,7 +651,7 @@ static int vfe_set_clock_rates(struct vfe_device *vfe) int i, j; int ret; - for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) { + for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) { ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity, &pixel_clock[i]); if (ret) @@ -550,7 +665,7 @@ static int vfe_set_clock_rates(struct vfe_device *vfe) u64 min_rate = 0; long rate; - for (j = VFE_LINE_RDI0; j < vfe->line_num; j++) { + for (j = VFE_LINE_RDI0; j < vfe->res->line_num; j++) { u32 tmp; u8 bpp; @@ -559,9 +674,9 @@ static int vfe_set_clock_rates(struct vfe_device *vfe) } else { struct vfe_line *l = &vfe->line[j]; - bpp = vfe_get_bpp(l->formats, - l->nformats, - l->fmt[MSM_VFE_PAD_SINK].code); + bpp = camss_format_get_bpp(l->formats, + l->nformats, + l->fmt[MSM_VFE_PAD_SINK].code); tmp = pixel_clock[j] * bpp / 64; } @@ -617,7 +732,7 @@ static int vfe_check_clock_rates(struct vfe_device *vfe) int i, j; int ret; - for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) { + for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) { ret = camss_get_pixel_clock(&vfe->line[i].subdev.entity, &pixel_clock[i]); if (ret) @@ -631,7 +746,7 @@ static int vfe_check_clock_rates(struct vfe_device *vfe) u64 min_rate = 0; unsigned long rate; - for (j = VFE_LINE_RDI0; j < vfe->line_num; j++) { + for (j = VFE_LINE_RDI0; j < vfe->res->line_num; j++) { u32 tmp; u8 bpp; @@ -640,9 +755,9 @@ static int vfe_check_clock_rates(struct vfe_device *vfe) } else { struct vfe_line *l = &vfe->line[j]; - bpp = vfe_get_bpp(l->formats, - l->nformats, - l->fmt[MSM_VFE_PAD_SINK].code); + bpp = camss_format_get_bpp(l->formats, + l->nformats, + l->fmt[MSM_VFE_PAD_SINK].code); tmp = pixel_clock[j] * bpp / 64; } @@ -674,7 +789,7 @@ int vfe_get(struct vfe_device *vfe) mutex_lock(&vfe->power_lock); if (vfe->power_count == 0) { - ret = vfe->ops->pm_domain_on(vfe); + ret = vfe->res->hw_ops->pm_domain_on(vfe); if (ret < 0) goto error_pm_domain; @@ -699,7 +814,7 @@ int vfe_get(struct vfe_device *vfe) vfe_init_outputs(vfe); - vfe->ops->hw_version(vfe); + vfe->res->hw_ops->hw_version(vfe); } else { ret = vfe_check_clock_rates(vfe); if (ret < 0) @@ -717,7 +832,7 @@ error_reset: error_pm_runtime_get: pm_runtime_put_sync(vfe->camss->dev); error_domain_off: - vfe->ops->pm_domain_off(vfe); + vfe->res->hw_ops->pm_domain_off(vfe); error_pm_domain: mutex_unlock(&vfe->power_lock); @@ -739,11 +854,11 @@ void vfe_put(struct vfe_device *vfe) } else if (vfe->power_count == 1) { if (vfe->was_streaming) { vfe->was_streaming = 0; - vfe->ops->vfe_halt(vfe); + vfe->res->hw_ops->vfe_halt(vfe); } camss_disable_clocks(vfe->nclocks, vfe->clock); pm_runtime_put_sync(vfe->camss->dev); - vfe->ops->pm_domain_off(vfe); + vfe->res->hw_ops->pm_domain_off(vfe); } vfe->power_count--; @@ -833,12 +948,12 @@ static int vfe_set_stream(struct v4l2_subdev *sd, int enable) if (enable) { line->output.state = VFE_OUTPUT_RESERVED; - ret = vfe->ops->vfe_enable(line); + ret = vfe->res->hw_ops->vfe_enable(line); if (ret < 0) dev_err(vfe->camss->dev, "Failed to enable vfe outputs\n"); } else { - ret = vfe->ops->vfe_disable(line); + ret = vfe->res->hw_ops->vfe_disable(line); if (ret < 0) dev_err(vfe->camss->dev, "Failed to disable vfe outputs\n"); @@ -1375,23 +1490,24 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe, int i, j; int ret; - vfe->ops = res->ops; - - if (!res->line_num) + if (!res->vfe.line_num) return -EINVAL; + vfe->res = &res->vfe; + vfe->res->hw_ops->subdev_init(dev, vfe); + /* Power domain */ - if (res->pd_name) { + if (res->vfe.pd_name) { vfe->genpd = dev_pm_domain_attach_by_name(camss->dev, - res->pd_name); + res->vfe.pd_name); if (IS_ERR(vfe->genpd)) { ret = PTR_ERR(vfe->genpd); return ret; } } - if (!vfe->genpd && res->has_pd) { + if (!vfe->genpd && res->vfe.has_pd) { /* * Legacy magic index. * Requires @@ -1408,9 +1524,6 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe, return PTR_ERR(vfe->genpd); } - vfe->line_num = res->line_num; - vfe->ops->subdev_init(dev, vfe); - /* Memory */ vfe->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]); @@ -1428,7 +1541,7 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe, vfe->irq = ret; snprintf(vfe->irq_name, sizeof(vfe->irq_name), "%s_%s%d", dev_name(dev), MSM_VFE_NAME, id); - ret = devm_request_irq(dev, vfe->irq, vfe->ops->isr, + ret = devm_request_irq(dev, vfe->irq, vfe->res->hw_ops->isr, IRQF_TRIGGER_RISING, vfe->irq_name, vfe); if (ret < 0) { dev_err(dev, "request_irq failed: %d\n", ret); @@ -1487,7 +1600,7 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe, vfe->id = id; vfe->reg_update = 0; - for (i = VFE_LINE_RDI0; i < vfe->line_num; i++) { + for (i = VFE_LINE_RDI0; i < vfe->res->line_num; i++) { struct vfe_line *l = &vfe->line[i]; l->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; @@ -1496,31 +1609,12 @@ int msm_vfe_subdev_init(struct camss *camss, struct vfe_device *vfe, init_completion(&l->output.sof); init_completion(&l->output.reg_update); - switch (camss->res->version) { - case CAMSS_8x16: - if (i == VFE_LINE_PIX) { - l->formats = formats_pix_8x16; - l->nformats = ARRAY_SIZE(formats_pix_8x16); - } else { - l->formats = formats_rdi_8x16; - l->nformats = ARRAY_SIZE(formats_rdi_8x16); - } - break; - case CAMSS_8x96: - case CAMSS_660: - if (i == VFE_LINE_PIX) { - l->formats = formats_pix_8x96; - l->nformats = ARRAY_SIZE(formats_pix_8x96); - } else { - l->formats = formats_rdi_8x96; - l->nformats = ARRAY_SIZE(formats_rdi_8x96); - } - break; - case CAMSS_845: - case CAMSS_8250: - l->formats = formats_rdi_845; - l->nformats = ARRAY_SIZE(formats_rdi_845); - break; + if (i == VFE_LINE_PIX) { + l->nformats = res->vfe.formats_pix->nformats; + l->formats = res->vfe.formats_pix->formats; + } else { + l->nformats = res->vfe.formats_rdi->nformats; + l->formats = res->vfe.formats_rdi->formats; } } @@ -1595,6 +1689,24 @@ static const struct media_entity_operations vfe_media_ops = { .link_validate = v4l2_subdev_link_validate, }; +static int vfe_bpl_align(struct vfe_device *vfe) +{ + int ret = 8; + + switch (vfe->camss->res->version) { + case CAMSS_7280: + case CAMSS_8250: + case CAMSS_8280XP: + case CAMSS_845: + ret = 16; + break; + default: + break; + } + + return ret; +} + /* * msm_vfe_register_entities - Register subdev node for VFE module * @vfe: VFE device @@ -1617,7 +1729,7 @@ int msm_vfe_register_entities(struct vfe_device *vfe, int ret; int i; - for (i = 0; i < vfe->line_num; i++) { + for (i = 0; i < vfe->res->line_num; i++) { char name[32]; sd = &vfe->line[i].subdev; @@ -1661,20 +1773,19 @@ int msm_vfe_register_entities(struct vfe_device *vfe, } video_out->ops = &vfe->video_ops; - if (vfe->camss->res->version == CAMSS_845 || - vfe->camss->res->version == CAMSS_8250) - video_out->bpl_alignment = 16; - else - video_out->bpl_alignment = 8; + video_out->bpl_alignment = vfe_bpl_align(vfe); video_out->line_based = 0; if (i == VFE_LINE_PIX) { video_out->bpl_alignment = 16; video_out->line_based = 1; } + + video_out->nformats = vfe->line[i].nformats; + video_out->formats = vfe->line[i].formats; + snprintf(name, ARRAY_SIZE(name), "%s%d_%s%d", MSM_VFE_NAME, vfe->id, "video", i); - ret = msm_video_register(video_out, v4l2_dev, name, - i == VFE_LINE_PIX ? 1 : 0); + ret = msm_video_register(video_out, v4l2_dev, name); if (ret < 0) { dev_err(dev, "Failed to register video node: %d\n", ret); @@ -1728,7 +1839,7 @@ void msm_vfe_unregister_entities(struct vfe_device *vfe) mutex_destroy(&vfe->power_lock); mutex_destroy(&vfe->stream_lock); - for (i = 0; i < vfe->line_num; i++) { + for (i = 0; i < vfe->res->line_num; i++) { struct v4l2_subdev *sd = &vfe->line[i].subdev; struct camss_video *video_out = &vfe->line[i].video_out; @@ -1740,5 +1851,5 @@ void msm_vfe_unregister_entities(struct vfe_device *vfe) bool vfe_is_lite(struct vfe_device *vfe) { - return vfe->camss->res->vfe_res[vfe->id].is_lite; + return vfe->camss->res->vfe_res[vfe->id].vfe.is_lite; } diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h index 0572c9b08e11..10e2cc3c0b83 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.h +++ b/drivers/media/platform/qcom/camss/camss-vfe.h @@ -92,7 +92,7 @@ struct vfe_line { struct v4l2_rect crop; struct camss_video video_out; struct vfe_output output; - const struct vfe_format *formats; + const struct camss_format_info *formats; unsigned int nformats; }; @@ -126,6 +126,16 @@ struct vfe_isr_ops { void (*wm_done)(struct vfe_device *vfe, u8 wm); }; +struct vfe_subdev_resources { + bool is_lite; + u8 line_num; + bool has_pd; + char *pd_name; + const struct vfe_hw_ops *hw_ops; + const struct camss_formats *formats_rdi; + const struct camss_formats *formats_pix; +}; + struct vfe_device { struct camss *camss; u8 id; @@ -143,10 +153,9 @@ struct vfe_device { spinlock_t output_lock; enum vfe_line_id wm_output_map[MSM_VFE_IMAGE_MASTERS_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_subdev_resources *res; const struct vfe_hw_ops_gen1 *ops_gen1; struct vfe_isr_ops isr_ops; struct camss_video_ops video_ops; @@ -217,6 +226,13 @@ void vfe_pm_domain_off(struct vfe_device *vfe); */ int vfe_pm_domain_on(struct vfe_device *vfe); +extern const struct camss_formats vfe_formats_rdi_8x16; +extern const struct camss_formats vfe_formats_pix_8x16; +extern const struct camss_formats vfe_formats_rdi_8x96; +extern const struct camss_formats vfe_formats_pix_8x96; +extern const struct camss_formats vfe_formats_rdi_845; +extern const struct camss_formats vfe_formats_pix_845; + 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; diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index a89da5ef4710..aa021fd5e123 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -24,269 +24,10 @@ #define CAMSS_FRAME_MAX_HEIGHT_RDI 8191 #define CAMSS_FRAME_MAX_HEIGHT_PIX 4096 -struct fract { - u8 numerator; - u8 denominator; -}; - -/* - * struct camss_format_info - ISP media bus format information - * @code: V4L2 media bus format code - * @pixelformat: V4L2 pixel format FCC identifier - * @planes: Number of planes - * @hsub: Horizontal subsampling (for each plane) - * @vsub: Vertical subsampling (for each plane) - * @bpp: Bits per pixel when stored in memory (for each plane) - */ -struct camss_format_info { - u32 code; - u32 pixelformat; - u8 planes; - struct fract hsub[3]; - struct fract vsub[3]; - unsigned int bpp[3]; -}; - -static const struct camss_format_info formats_rdi_8x16[] = { - { MEDIA_BUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_VYUY8_1X16, V4L2_PIX_FMT_VYUY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YVYU8_1X16, V4L2_PIX_FMT_YVYU, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_Y10_1X10, V4L2_PIX_FMT_Y10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, -}; - -static const struct camss_format_info formats_rdi_8x96[] = { - { MEDIA_BUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_VYUY8_1X16, V4L2_PIX_FMT_VYUY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YVYU8_1X16, V4L2_PIX_FMT_YVYU, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_PIX_FMT_SBGGR10, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SBGGR14_1X14, V4L2_PIX_FMT_SBGGR14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_SGBRG14_1X14, V4L2_PIX_FMT_SGBRG14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_SGRBG14_1X14, V4L2_PIX_FMT_SGRBG14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_SRGGB14_1X14, V4L2_PIX_FMT_SRGGB14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_Y10_1X10, V4L2_PIX_FMT_Y10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, V4L2_PIX_FMT_Y10, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, -}; - -static const struct camss_format_info formats_rdi_845[] = { - { MEDIA_BUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_VYUY8_1X16, V4L2_PIX_FMT_VYUY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YVYU8_1X16, V4L2_PIX_FMT_YVYU, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_PIX_FMT_SBGGR8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SGBRG8_1X8, V4L2_PIX_FMT_SGBRG8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SGRBG8_1X8, V4L2_PIX_FMT_SGRBG8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SRGGB8_1X8, V4L2_PIX_FMT_SRGGB8, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_PIX_FMT_SBGGR10, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 12 } }, - { MEDIA_BUS_FMT_SBGGR14_1X14, V4L2_PIX_FMT_SBGGR14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_SGBRG14_1X14, V4L2_PIX_FMT_SGBRG14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_SGRBG14_1X14, V4L2_PIX_FMT_SGRBG14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_SRGGB14_1X14, V4L2_PIX_FMT_SRGGB14P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 14 } }, - { MEDIA_BUS_FMT_Y8_1X8, V4L2_PIX_FMT_GREY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 8 } }, - { MEDIA_BUS_FMT_Y10_1X10, V4L2_PIX_FMT_Y10P, 1, - { { 1, 1 } }, { { 1, 1 } }, { 10 } }, - { MEDIA_BUS_FMT_Y10_2X8_PADHI_LE, V4L2_PIX_FMT_Y10, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, -}; - -static const struct camss_format_info formats_pix_8x16[] = { - { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1X16, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1X16, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1X16, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1X16, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, -}; - -static const struct camss_format_info formats_pix_8x96[] = { - { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV12, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1_5X8, V4L2_PIX_FMT_NV21, 1, - { { 1, 1 } }, { { 2, 3 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1X16, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1X16, V4L2_PIX_FMT_NV16, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_YVYU8_1X16, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_VYUY8_1X16, V4L2_PIX_FMT_NV61, 1, - { { 1, 1 } }, { { 1, 2 } }, { 8 } }, - { MEDIA_BUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_VYUY8_1X16, V4L2_PIX_FMT_VYUY, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, - { MEDIA_BUS_FMT_YVYU8_1X16, V4L2_PIX_FMT_YVYU, 1, - { { 1, 1 } }, { { 1, 1 } }, { 16 } }, -}; - /* ----------------------------------------------------------------------------- * Helper functions */ -static int video_find_format(u32 code, u32 pixelformat, - const struct camss_format_info *formats, - unsigned int nformats) -{ - int i; - - for (i = 0; i < nformats; i++) { - if (formats[i].code == code && - formats[i].pixelformat == pixelformat) - return i; - } - - for (i = 0; i < nformats; i++) - if (formats[i].code == code) - return i; - - WARN_ON(1); - - return -EINVAL; -} - /* * video_mbus_to_pix_mp - Convert v4l2_mbus_framefmt to v4l2_pix_format_mplane * @mbus: v4l2_mbus_framefmt format (input) @@ -359,9 +100,8 @@ static int video_get_subdev_format(struct camss_video *video, if (ret) return ret; - ret = video_find_format(fmt.format.code, - format->fmt.pix_mp.pixelformat, - video->formats, video->nformats); + ret = camss_format_find_format(fmt.format.code, format->fmt.pix_mp.pixelformat, + video->formats, video->nformats); if (ret < 0) return ret; @@ -557,12 +297,6 @@ static void video_stop_streaming(struct vb2_queue *q) ret = v4l2_subdev_call(subdev, video, s_stream, 0); - if (entity->use_count > 1) { - /* Don't stop if other instances of the pipeline are still running */ - dev_dbg(video->camss->dev, "Video pipeline still used, don't stop streaming.\n"); - return; - } - if (ret) { dev_err(video->camss->dev, "Video pipeline stop failed: %d\n", ret); return; @@ -576,8 +310,6 @@ static void video_stop_streaming(struct vb2_queue *q) static const struct vb2_ops msm_video_vb2_q_ops = { .queue_setup = video_queue_setup, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, .buf_init = video_buf_init, .buf_prepare = video_buf_prepare, .buf_queue = video_buf_queue, @@ -969,7 +701,7 @@ static int msm_video_init_format(struct camss_video *video) */ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, - const char *name, int is_pix) + const char *name) { struct media_pad *pad = &video->pad; struct video_device *vdev; @@ -1006,33 +738,6 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, mutex_init(&video->lock); - switch (video->camss->res->version) { - case CAMSS_8x16: - if (is_pix) { - video->formats = formats_pix_8x16; - video->nformats = ARRAY_SIZE(formats_pix_8x16); - } else { - video->formats = formats_rdi_8x16; - video->nformats = ARRAY_SIZE(formats_rdi_8x16); - } - break; - case CAMSS_8x96: - case CAMSS_660: - if (is_pix) { - video->formats = formats_pix_8x96; - video->nformats = ARRAY_SIZE(formats_pix_8x96); - } else { - video->formats = formats_rdi_8x96; - video->nformats = ARRAY_SIZE(formats_rdi_8x96); - } - break; - case CAMSS_845: - case CAMSS_8250: - video->formats = formats_rdi_845; - video->nformats = ARRAY_SIZE(formats_rdi_845); - break; - } - ret = msm_video_init_format(video); if (ret < 0) { dev_err(v4l2_dev->dev, "Failed to init format: %d\n", ret); diff --git a/drivers/media/platform/qcom/camss/camss-video.h b/drivers/media/platform/qcom/camss/camss-video.h index bdbae8424140..d3e56e240a88 100644 --- a/drivers/media/platform/qcom/camss/camss-video.h +++ b/drivers/media/platform/qcom/camss/camss-video.h @@ -33,8 +33,6 @@ struct camss_video_ops { enum vb2_buffer_state state); }; -struct camss_format_info; - struct camss_video { struct camss *camss; struct vb2_queue vb2_q; @@ -53,7 +51,7 @@ struct camss_video { }; int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, - const char *name, int is_pix); + const char *name); void msm_video_unregister(struct camss_video *video); diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 58f4be660290..a85e9df0f301 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -32,6 +32,8 @@ #define CAMSS_CLOCK_MARGIN_NUMERATOR 105 #define CAMSS_CLOCK_MARGIN_DENOMINATOR 100 +static const struct parent_dev_ops vfe_parent_dev_ops; + static const struct camss_subdev_resources csiphy_res_8x16[] = { /* CSIPHY0 */ { @@ -43,7 +45,10 @@ static const struct camss_subdev_resources csiphy_res_8x16[] = { { 100000000, 200000000 } }, .reg = { "csiphy0", "csiphy0_clk_mux" }, .interrupt = { "csiphy0" }, - .ops = &csiphy_ops_2ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_2ph_1_0, + .formats = &csiphy_formats_8x16 + } }, /* CSIPHY1 */ @@ -56,7 +61,10 @@ static const struct camss_subdev_resources csiphy_res_8x16[] = { { 100000000, 200000000 } }, .reg = { "csiphy1", "csiphy1_clk_mux" }, .interrupt = { "csiphy1" }, - .ops = &csiphy_ops_2ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_2ph_1_0, + .formats = &csiphy_formats_8x16 + } } }; @@ -76,7 +84,11 @@ static const struct camss_subdev_resources csid_res_8x16[] = { { 0 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, - .ops = &csid_ops_4_1, + .csid = { + .hw_ops = &csid_ops_4_1, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_1 + } }, /* CSID1 */ @@ -94,7 +106,11 @@ static const struct camss_subdev_resources csid_res_8x16[] = { { 0 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, - .ops = &csid_ops_4_1, + .csid = { + .hw_ops = &csid_ops_4_1, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_1 + } }, }; @@ -105,8 +121,7 @@ static const struct camss_subdev_resources ispif_res_8x16 = { "csi1", "csi1_pix", "csi1_rdi" }, .clock_for_reset = { "vfe0", "csi_vfe0" }, .reg = { "ispif", "csi_clk_mux" }, - .interrupt = { "ispif" } - + .interrupt = { "ispif" }, }; static const struct camss_subdev_resources vfe_res_8x16[] = { @@ -128,11 +143,169 @@ static const struct camss_subdev_resources vfe_res_8x16[] = { { 0 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, - .line_num = 3, - .ops = &vfe_ops_4_1 + .vfe = { + .line_num = 3, + .hw_ops = &vfe_ops_4_1, + .formats_rdi = &vfe_formats_rdi_8x16, + .formats_pix = &vfe_formats_pix_8x16 + } } }; +static const struct camss_subdev_resources csid_res_8x53[] = { + /* CSID0 */ + { + .regulators = { "vdda" }, + .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb", + "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 100000000, 200000000, 310000000, + 400000000, 465000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } + }, + + /* CSID1 */ + { + .regulators = { "vdda" }, + .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb", + "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 100000000, 200000000, 310000000, + 400000000, 465000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } + }, + + /* CSID2 */ + { + .regulators = { "vdda" }, + .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb", + "csi2", "csi2_phy", "csi2_pix", "csi2_rdi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 100000000, 200000000, 310000000, + 400000000, 465000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } + }, +}; + +static const struct camss_subdev_resources ispif_res_8x53 = { + /* ISPIF */ + .clock = { "top_ahb", "ahb", "ispif_ahb", + "csi0", "csi0_pix", "csi0_rdi", + "csi1", "csi1_pix", "csi1_rdi", + "csi2", "csi2_pix", "csi2_rdi" }, + .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" }, + .reg = { "ispif", "csi_clk_mux" }, + .interrupt = { "ispif" }, +}; + +static const struct camss_subdev_resources vfe_res_8x53[] = { + /* VFE0 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "ispif_ahb", + "vfe0", "csi_vfe0", "vfe0_ahb", "vfe0_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 50000000, 100000000, 133330000, + 160000000, 200000000, 266670000, + 310000000, 400000000, 465000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .has_pd = true, + .pd_name = "vfe0", + .hw_ops = &vfe_ops_4_1, + .formats_rdi = &vfe_formats_rdi_8x16, + .formats_pix = &vfe_formats_pix_8x16 + } + }, + + /* VFE1 */ + { + .regulators = {}, + .clock = { "top_ahb", "ahb", "ispif_ahb", + "vfe1", "csi_vfe1", "vfe1_ahb", "vfe1_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 0 }, + { 50000000, 100000000, 133330000, + 160000000, 200000000, 266670000, + 310000000, 400000000, 465000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .has_pd = true, + .pd_name = "vfe1", + .hw_ops = &vfe_ops_4_1, + .formats_rdi = &vfe_formats_rdi_8x16, + .formats_pix = &vfe_formats_pix_8x16 + } + } +}; + +static const struct resources_icc icc_res_8x53[] = { + { + .name = "cam_ahb", + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, + }, + { + .name = "cam_vfe0_mem", + .icc_bw_tbl.avg = 939524, + .icc_bw_tbl.peak = 1342177, + }, + { + .name = "cam_vfe1_mem", + .icc_bw_tbl.avg = 939524, + .icc_bw_tbl.peak = 1342177, + }, +}; + static const struct camss_subdev_resources csiphy_res_8x96[] = { /* CSIPHY0 */ { @@ -144,7 +317,10 @@ static const struct camss_subdev_resources csiphy_res_8x96[] = { { 100000000, 200000000, 266666667 } }, .reg = { "csiphy0", "csiphy0_clk_mux" }, .interrupt = { "csiphy0" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_8x96 + } }, /* CSIPHY1 */ @@ -157,7 +333,10 @@ static const struct camss_subdev_resources csiphy_res_8x96[] = { { 100000000, 200000000, 266666667 } }, .reg = { "csiphy1", "csiphy1_clk_mux" }, .interrupt = { "csiphy1" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_8x96 + } }, /* CSIPHY2 */ @@ -170,7 +349,10 @@ static const struct camss_subdev_resources csiphy_res_8x96[] = { { 100000000, 200000000, 266666667 } }, .reg = { "csiphy2", "csiphy2_clk_mux" }, .interrupt = { "csiphy2" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_8x96 + } } }; @@ -190,7 +372,11 @@ static const struct camss_subdev_resources csid_res_8x96[] = { { 0 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, - .ops = &csid_ops_4_7, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } }, /* CSID1 */ @@ -208,7 +394,11 @@ static const struct camss_subdev_resources csid_res_8x96[] = { { 0 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, - .ops = &csid_ops_4_7, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } }, /* CSID2 */ @@ -226,7 +416,11 @@ static const struct camss_subdev_resources csid_res_8x96[] = { { 0 } }, .reg = { "csid2" }, .interrupt = { "csid2" }, - .ops = &csid_ops_4_7, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } }, /* CSID3 */ @@ -244,7 +438,11 @@ static const struct camss_subdev_resources csid_res_8x96[] = { { 0 } }, .reg = { "csid3" }, .interrupt = { "csid3" }, - .ops = &csid_ops_4_7, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } } }; @@ -257,7 +455,7 @@ static const struct camss_subdev_resources ispif_res_8x96 = { "csi3", "csi3_pix", "csi3_rdi" }, .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" }, .reg = { "ispif", "csi_clk_mux" }, - .interrupt = { "ispif" } + .interrupt = { "ispif" }, }; static const struct camss_subdev_resources vfe_res_8x96[] = { @@ -277,9 +475,13 @@ static const struct camss_subdev_resources vfe_res_8x96[] = { { 0 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, - .line_num = 3, - .has_pd = true, - .ops = &vfe_ops_4_7 + .vfe = { + .line_num = 3, + .has_pd = true, + .hw_ops = &vfe_ops_4_7, + .formats_rdi = &vfe_formats_rdi_8x96, + .formats_pix = &vfe_formats_pix_8x96 + } }, /* VFE1 */ @@ -298,9 +500,13 @@ static const struct camss_subdev_resources vfe_res_8x96[] = { { 0 } }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, - .line_num = 3, - .has_pd = true, - .ops = &vfe_ops_4_7 + .vfe = { + .line_num = 3, + .has_pd = true, + .hw_ops = &vfe_ops_4_7, + .formats_rdi = &vfe_formats_rdi_8x96, + .formats_pix = &vfe_formats_pix_8x96 + } } }; @@ -317,7 +523,10 @@ static const struct camss_subdev_resources csiphy_res_660[] = { { 0 } }, .reg = { "csiphy0", "csiphy0_clk_mux" }, .interrupt = { "csiphy0" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_8x96 + } }, /* CSIPHY1 */ @@ -332,7 +541,10 @@ static const struct camss_subdev_resources csiphy_res_660[] = { { 0 } }, .reg = { "csiphy1", "csiphy1_clk_mux" }, .interrupt = { "csiphy1" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_8x96 + } }, /* CSIPHY2 */ @@ -347,7 +559,10 @@ static const struct camss_subdev_resources csiphy_res_660[] = { { 0 } }, .reg = { "csiphy2", "csiphy2_clk_mux" }, .interrupt = { "csiphy2" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_8x96 + } } }; @@ -370,7 +585,11 @@ static const struct camss_subdev_resources csid_res_660[] = { { 0 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, - .ops = &csid_ops_4_7, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } }, /* CSID1 */ @@ -391,7 +610,11 @@ static const struct camss_subdev_resources csid_res_660[] = { { 0 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, - .ops = &csid_ops_4_7, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } }, /* CSID2 */ @@ -412,7 +635,11 @@ static const struct camss_subdev_resources csid_res_660[] = { { 0 } }, .reg = { "csid2" }, .interrupt = { "csid2" }, - .ops = &csid_ops_4_7, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } }, /* CSID3 */ @@ -433,7 +660,11 @@ static const struct camss_subdev_resources csid_res_660[] = { { 0 } }, .reg = { "csid3" }, .interrupt = { "csid3" }, - .ops = &csid_ops_4_7, + .csid = { + .hw_ops = &csid_ops_4_7, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_4_7 + } } }; @@ -446,7 +677,7 @@ static const struct camss_subdev_resources ispif_res_660 = { "csi3", "csi3_pix", "csi3_rdi" }, .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" }, .reg = { "ispif", "csi_clk_mux" }, - .interrupt = { "ispif" } + .interrupt = { "ispif" }, }; static const struct camss_subdev_resources vfe_res_660[] = { @@ -469,9 +700,13 @@ static const struct camss_subdev_resources vfe_res_660[] = { { 0 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, - .line_num = 3, - .has_pd = true, - .ops = &vfe_ops_4_8 + .vfe = { + .line_num = 3, + .has_pd = true, + .hw_ops = &vfe_ops_4_8, + .formats_rdi = &vfe_formats_rdi_8x96, + .formats_pix = &vfe_formats_pix_8x96 + } }, /* VFE1 */ @@ -493,9 +728,13 @@ static const struct camss_subdev_resources vfe_res_660[] = { { 0 } }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, - .line_num = 3, - .has_pd = true, - .ops = &vfe_ops_4_8 + .vfe = { + .line_num = 3, + .has_pd = true, + .hw_ops = &vfe_ops_4_8, + .formats_rdi = &vfe_formats_rdi_8x96, + .formats_pix = &vfe_formats_pix_8x96 + } } }; @@ -516,7 +755,10 @@ static const struct camss_subdev_resources csiphy_res_845[] = { { 19200000, 240000000, 269333333 } }, .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY1 */ @@ -535,7 +777,10 @@ static const struct camss_subdev_resources csiphy_res_845[] = { { 19200000, 240000000, 269333333 } }, .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY2 */ @@ -554,7 +799,10 @@ static const struct camss_subdev_resources csiphy_res_845[] = { { 19200000, 240000000, 269333333 } }, .reg = { "csiphy2" }, .interrupt = { "csiphy2" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY3 */ @@ -573,7 +821,10 @@ static const struct camss_subdev_resources csiphy_res_845[] = { { 19200000, 240000000, 269333333 } }, .reg = { "csiphy3" }, .interrupt = { "csiphy3" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } } }; @@ -596,7 +847,11 @@ static const struct camss_subdev_resources csid_res_845[] = { { 384000000 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, - .ops = &csid_ops_gen2 + .csid = { + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } }, /* CSID1 */ @@ -617,7 +872,11 @@ static const struct camss_subdev_resources csid_res_845[] = { { 384000000 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, - .ops = &csid_ops_gen2 + .csid = { + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } }, /* CSID2 */ @@ -638,8 +897,12 @@ static const struct camss_subdev_resources csid_res_845[] = { { 384000000 } }, .reg = { "csid2" }, .interrupt = { "csid2" }, - .is_lite = true, - .ops = &csid_ops_gen2 + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } } }; @@ -662,9 +925,13 @@ static const struct camss_subdev_resources vfe_res_845[] = { { 384000000 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, - .line_num = 4, - .has_pd = true, - .ops = &vfe_ops_170 + .vfe = { + .line_num = 4, + .has_pd = true, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } }, /* VFE1 */ @@ -685,9 +952,13 @@ static const struct camss_subdev_resources vfe_res_845[] = { { 384000000 } }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, - .line_num = 4, - .has_pd = true, - .ops = &vfe_ops_170 + .vfe = { + .line_num = 4, + .has_pd = true, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } }, /* VFE-lite */ @@ -707,79 +978,101 @@ static const struct camss_subdev_resources vfe_res_845[] = { { 384000000 } }, .reg = { "vfe_lite" }, .interrupt = { "vfe_lite" }, - .is_lite = true, - .line_num = 4, - .ops = &vfe_ops_170 + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } } }; static const struct camss_subdev_resources csiphy_res_8250[] = { /* CSIPHY0 */ { - .regulators = {}, + .regulators = { "vdda-phy", "vdda-pll" }, .clock = { "csiphy0", "csiphy0_timer" }, .clock_rate = { { 400000000 }, { 300000000 } }, .reg = { "csiphy0" }, .interrupt = { "csiphy0" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY1 */ { - .regulators = {}, + .regulators = { "vdda-phy", "vdda-pll" }, .clock = { "csiphy1", "csiphy1_timer" }, .clock_rate = { { 400000000 }, { 300000000 } }, .reg = { "csiphy1" }, .interrupt = { "csiphy1" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY2 */ { - .regulators = {}, + .regulators = { "vdda-phy", "vdda-pll" }, .clock = { "csiphy2", "csiphy2_timer" }, .clock_rate = { { 400000000 }, { 300000000 } }, .reg = { "csiphy2" }, .interrupt = { "csiphy2" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY3 */ { - .regulators = {}, + .regulators = { "vdda-phy", "vdda-pll" }, .clock = { "csiphy3", "csiphy3_timer" }, .clock_rate = { { 400000000 }, { 300000000 } }, .reg = { "csiphy3" }, .interrupt = { "csiphy3" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY4 */ { - .regulators = {}, + .regulators = { "vdda-phy", "vdda-pll" }, .clock = { "csiphy4", "csiphy4_timer" }, .clock_rate = { { 400000000 }, { 300000000 } }, .reg = { "csiphy4" }, .interrupt = { "csiphy4" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } }, /* CSIPHY5 */ { - .regulators = {}, + .regulators = { "vdda-phy", "vdda-pll" }, .clock = { "csiphy5", "csiphy5_timer" }, .clock_rate = { { 400000000 }, { 300000000 } }, .reg = { "csiphy5" }, .interrupt = { "csiphy5" }, - .ops = &csiphy_ops_3ph_1_0 + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } } }; static const struct camss_subdev_resources csid_res_8250[] = { /* CSID0 */ { - .regulators = { "vdda-phy", "vdda-pll" }, + .regulators = {}, .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0", "vfe0_areg", "vfe0_ahb" }, .clock_rate = { { 400000000 }, { 400000000 }, @@ -788,11 +1081,15 @@ static const struct camss_subdev_resources csid_res_8250[] = { { 0 } }, .reg = { "csid0" }, .interrupt = { "csid0" }, - .ops = &csid_ops_gen2 + .csid = { + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } }, /* CSID1 */ { - .regulators = { "vdda-phy", "vdda-pll" }, + .regulators = {}, .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1", "vfe1_areg", "vfe1_ahb" }, .clock_rate = { { 400000000 }, { 400000000 }, @@ -801,11 +1098,15 @@ static const struct camss_subdev_resources csid_res_8250[] = { { 0 } }, .reg = { "csid1" }, .interrupt = { "csid1" }, - .ops = &csid_ops_gen2 + .csid = { + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } }, /* CSID2 */ { - .regulators = { "vdda-phy", "vdda-pll" }, + .regulators = {}, .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" }, .clock_rate = { { 400000000 }, { 400000000 }, @@ -813,12 +1114,16 @@ static const struct camss_subdev_resources csid_res_8250[] = { { 0 } }, .reg = { "csid2" }, .interrupt = { "csid2" }, - .is_lite = true, - .ops = &csid_ops_gen2 + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } }, /* CSID3 */ { - .regulators = { "vdda-phy", "vdda-pll" }, + .regulators = {}, .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" }, .clock_rate = { { 400000000 }, { 400000000 }, @@ -826,8 +1131,12 @@ static const struct camss_subdev_resources csid_res_8250[] = { { 0 } }, .reg = { "csid3" }, .interrupt = { "csid3" }, - .is_lite = true, - .ops = &csid_ops_gen2 + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } } }; @@ -849,10 +1158,14 @@ static const struct camss_subdev_resources vfe_res_8250[] = { { 0 } }, .reg = { "vfe0" }, .interrupt = { "vfe0" }, - .pd_name = "ife0", - .line_num = 3, - .has_pd = true, - .ops = &vfe_ops_480 + .vfe = { + .line_num = 3, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_480, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } }, /* VFE1 */ { @@ -871,10 +1184,14 @@ static const struct camss_subdev_resources vfe_res_8250[] = { { 0 } }, .reg = { "vfe1" }, .interrupt = { "vfe1" }, - .pd_name = "ife1", - .line_num = 3, - .has_pd = true, - .ops = &vfe_ops_480 + .vfe = { + .line_num = 3, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_480, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } }, /* VFE2 (lite) */ { @@ -892,9 +1209,13 @@ static const struct camss_subdev_resources vfe_res_8250[] = { { 0 } }, .reg = { "vfe_lite0" }, .interrupt = { "vfe_lite0" }, - .is_lite = true, - .line_num = 4, - .ops = &vfe_ops_480 + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_480, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } }, /* VFE3 (lite) */ { @@ -912,9 +1233,13 @@ static const struct camss_subdev_resources vfe_res_8250[] = { { 0 } }, .reg = { "vfe_lite1" }, .interrupt = { "vfe_lite1" }, - .is_lite = true, - .line_num = 4, - .ops = &vfe_ops_480 + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_480, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } }, }; @@ -941,6 +1266,678 @@ static const struct resources_icc icc_res_sm8250[] = { }, }; +static const struct camss_subdev_resources csiphy_res_7280[] = { + /* CSIPHY0 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy0", "csiphy0_timer" }, + .clock_rate = { { 300000000, 400000000 }, + { 300000000 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sc7280 + } + }, + /* CSIPHY1 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy1", "csiphy1_timer" }, + .clock_rate = { { 300000000, 400000000 }, + { 300000000 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sc7280 + } + }, + /* CSIPHY2 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy2", "csiphy2_timer" }, + .clock_rate = { { 300000000, 400000000 }, + { 300000000 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sc7280 + } + }, + /* CSIPHY3 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy3", "csiphy3_timer" }, + .clock_rate = { { 300000000, 400000000 }, + { 300000000 } }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sc7280 + } + }, + /* CSIPHY4 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + + .clock = { "csiphy4", "csiphy4_timer" }, + .clock_rate = { { 300000000, 400000000 }, + { 300000000 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sc7280 + } + }, +}; + +static const struct camss_subdev_resources csid_res_7280[] = { + /* CSID0 */ + { + .regulators = {}, + + .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0" }, + .clock_rate = { { 300000000, 400000000 }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 } + }, + + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .regulators = {}, + + .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1" }, + .clock_rate = { { 300000000, 400000000 }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 } + }, + + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .regulators = {}, + + .clock = { "vfe2_csid", "vfe2_cphy_rx", "vfe2" }, + .clock_rate = { { 300000000, 400000000 }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 } + }, + + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID3 */ + { + .regulators = {}, + + .clock = { "vfe_lite0_csid", "vfe_lite0_cphy_rx", "vfe_lite0" }, + .clock_rate = { { 300000000, 400000000 }, + { 0 }, + { 320000000, 400000000, 480000000, 600000000 } + }, + + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID4 */ + { + .regulators = {}, + + .clock = { "vfe_lite1_csid", "vfe_lite1_cphy_rx", "vfe_lite1" }, + .clock_rate = { { 300000000, 400000000 }, + { 0 }, + { 320000000, 400000000, 480000000, 600000000 } + }, + + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, +}; + +static const struct camss_subdev_resources vfe_res_7280[] = { + /* VFE0 */ + { + .regulators = {}, + + .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe0", + "vfe0_axi", "gcc_cam_hf_axi" }, + .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, + { 80000000 }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 }, + { 0 }, + { 0 } }, + + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 */ + { + .regulators = {}, + + .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe1", + "vfe1_axi", "gcc_cam_hf_axi" }, + .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, + { 80000000 }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 }, + { 0 }, + { 0 } }, + + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 */ + { + .regulators = {}, + + .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe2", + "vfe2_axi", "gcc_cam_hf_axi" }, + .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, + { 80000000 }, + { 0 }, + { 380000000, 510000000, 637000000, 760000000 }, + { 0 }, + { 0 } }, + + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .hw_ops = &vfe_ops_170, + .has_pd = true, + .pd_name = "ife2", + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE3 (lite) */ + { + .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", + "vfe_lite0", "gcc_cam_hf_axi" }, + .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, + { 80000000 }, + { 0 }, + { 320000000, 400000000, 480000000, 600000000 }, + { 0 } }, + + .regulators = {}, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE4 (lite) */ + { + .clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", + "vfe_lite1", "gcc_cam_hf_axi" }, + .clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 }, + { 80000000 }, + { 0 }, + { 320000000, 400000000, 480000000, 600000000 }, + { 0 } }, + + .regulators = {}, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + +static const struct resources_icc icc_res_sc7280[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 38400, + .icc_bw_tbl.peak = 76800, + }, + { + .name = "hf_0", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + +static const struct camss_subdev_resources csiphy_res_sc8280xp[] = { + /* CSIPHY0 */ + { + .regulators = {}, + .clock = { "csiphy0", "csiphy0_timer" }, + .clock_rate = { { 400000000 }, + { 300000000 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = {}, + .clock = { "csiphy1", "csiphy1_timer" }, + .clock_rate = { { 400000000 }, + { 300000000 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = {}, + .clock = { "csiphy2", "csiphy2_timer" }, + .clock_rate = { { 400000000 }, + { 300000000 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = {}, + .clock = { "csiphy3", "csiphy3_timer" }, + .clock_rate = { { 400000000 }, + { 300000000 } }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, +}; + +static const struct camss_subdev_resources csid_res_sc8280xp[] = { + /* CSID0 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0", "vfe0_axi" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1", "vfe1_axi" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "vfe2_csid", "vfe2_cphy_rx", "vfe2", "vfe2_axi" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID3 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "vfe3_csid", "vfe3_cphy_rx", "vfe3", "vfe3_axi" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, + { 0 } }, + .reg = { "csid3" }, + .interrupt = { "csid3" }, + .csid = { + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "vfe_lite0_csid", "vfe_lite0_cphy_rx", "vfe_lite0" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, }, + .reg = { "csid0_lite" }, + .interrupt = { "csid0_lite" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "vfe_lite1_csid", "vfe_lite1_cphy_rx", "vfe_lite1" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, }, + .reg = { "csid1_lite" }, + .interrupt = { "csid1_lite" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE2 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "vfe_lite2_csid", "vfe_lite2_cphy_rx", "vfe_lite2" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, }, + .reg = { "csid2_lite" }, + .interrupt = { "csid2_lite" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE3 */ + { + .regulators = { "vdda-phy", "vdda-pll" }, + .clock = { "vfe_lite3_csid", "vfe_lite3_cphy_rx", "vfe_lite3" }, + .clock_rate = { { 400000000, 480000000, 600000000 }, + { 0 }, + { 0 }, }, + .reg = { "csid3_lite" }, + .interrupt = { "csid3_lite" }, + .csid = { + .is_lite = true, + .hw_ops = &csid_ops_gen2, + .parent_dev_ops = &vfe_parent_dev_ops, + .formats = &csid_formats_gen2 + } + } +}; + +static const struct camss_subdev_resources vfe_res_sc8280xp[] = { + /* VFE0 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe0", "vfe0_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 400000000, 558000000, 637000000, 760000000 }, + { 0 }, }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 4, + .pd_name = "ife0", + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe1", "vfe1_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 400000000, 558000000, 637000000, 760000000 }, + { 0 }, }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 4, + .pd_name = "ife1", + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe2", "vfe2_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 400000000, 558000000, 637000000, 760000000 }, + { 0 }, }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 4, + .pd_name = "ife2", + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE3 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe3", "vfe3_axi" }, + .clock_rate = { { 0 }, + { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 400000000, 558000000, 637000000, 760000000 }, + { 0 }, }, + .reg = { "vfe3" }, + .interrupt = { "vfe3" }, + .vfe = { + .line_num = 4, + .pd_name = "ife3", + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE_0 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite0" }, + .clock_rate = { { 0 }, + { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 320000000, 400000000, 480000000, 600000000 }, }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE_1 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite1" }, + .clock_rate = { { 0 }, + { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 320000000, 400000000, 480000000, 600000000 }, }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE_2 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite2" }, + .clock_rate = { { 0 }, + { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 320000000, 400000000, 480000000, 600000000, }, }, + .reg = { "vfe_lite2" }, + .interrupt = { "vfe_lite2" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE_3 */ + { + .regulators = {}, + .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite3" }, + .clock_rate = { { 0 }, + { 0 }, + { 19200000, 80000000}, + { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 }, + { 320000000, 400000000, 480000000, 600000000 }, }, + .reg = { "vfe_lite3" }, + .interrupt = { "vfe_lite3" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_170, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + +static const struct resources_icc icc_res_sc8280xp[] = { + { + .name = "cam_ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + { + .name = "cam_hf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, + { + .name = "cam_sf_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, + { + .name = "cam_sf_icp_mnoc", + .icc_bw_tbl.avg = 2097152, + .icc_bw_tbl.peak = 2097152, + }, +}; + /* * camss_add_clock_margin - Add margin to clock frequency rate * @rate: Clock frequency rate @@ -1083,7 +2080,7 @@ int camss_pm_domain_on(struct camss *camss, int id) if (id < camss->res->vfe_num) { struct vfe_device *vfe = &camss->vfe[id]; - ret = vfe->ops->pm_domain_on(vfe); + ret = vfe->res->hw_ops->pm_domain_on(vfe); } return ret; @@ -1094,10 +2091,52 @@ void camss_pm_domain_off(struct camss *camss, int id) if (id < camss->res->vfe_num) { struct vfe_device *vfe = &camss->vfe[id]; - vfe->ops->pm_domain_off(vfe); + vfe->res->hw_ops->pm_domain_off(vfe); + } +} + +static int vfe_parent_dev_ops_get(struct camss *camss, int id) +{ + int ret = -EINVAL; + + if (id < camss->res->vfe_num) { + struct vfe_device *vfe = &camss->vfe[id]; + + ret = vfe_get(vfe); } + + return ret; } +static int vfe_parent_dev_ops_put(struct camss *camss, int id) +{ + if (id < camss->res->vfe_num) { + struct vfe_device *vfe = &camss->vfe[id]; + + vfe_put(vfe); + } + + return 0; +} + +static void __iomem +*vfe_parent_dev_ops_get_base_address(struct camss *camss, int id) +{ + if (id < camss->res->vfe_num) { + struct vfe_device *vfe = &camss->vfe[id]; + + return vfe->base; + } + + return NULL; +} + +static const struct parent_dev_ops vfe_parent_dev_ops = { + .get = vfe_parent_dev_ops_get, + .put = vfe_parent_dev_ops_put, + .get_base_address = vfe_parent_dev_ops_get_base_address +}; + /* * camss_of_parse_endpoint_node - Parse port endpoint node * @dev: Device @@ -1114,8 +2153,11 @@ static int camss_of_parse_endpoint_node(struct device *dev, struct v4l2_mbus_config_mipi_csi2 *mipi_csi2; struct v4l2_fwnode_endpoint vep = { { 0 } }; unsigned int i; + int ret; - v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep); + ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep); + if (ret) + return ret; csd->interface.csiphy_id = vep.base.port; @@ -1196,6 +2238,7 @@ err_cleanup: */ static int camss_init_subdevices(struct camss *camss) { + struct platform_device *pdev = to_platform_device(camss->dev); const struct camss_resources *res = camss->res; unsigned int i; int ret; @@ -1222,6 +2265,17 @@ static int camss_init_subdevices(struct camss *camss) } } + /* Get optional CSID wrapper regs shared between CSID devices */ + if (res->csid_wrapper_res) { + char *reg = res->csid_wrapper_res->reg; + void __iomem *base; + + base = devm_platform_ioremap_resource_byname(pdev, reg); + if (IS_ERR(base)) + return PTR_ERR(base); + camss->csid_wrapper_base = base; + } + for (i = 0; i < camss->res->csid_num; i++) { ret = msm_csid_subdev_init(camss, &camss->csid[i], &res->csid_res[i], i); @@ -1244,72 +2298,47 @@ static int camss_init_subdevices(struct camss *camss) } /* - * camss_register_entities - Register subdev nodes and create links + * camss_link_entities - Register subdev nodes and create links + * camss_link_err - print error in case link creation fails + * @src_name: name for source of the link + * @sink_name: name for sink of the link + */ +inline void camss_link_err(struct camss *camss, + const char *src_name, + const char *sink_name, + int ret) +{ + dev_err(camss->dev, + "Failed to link %s->%s entities: %d\n", + src_name, + sink_name, + ret); +} + +/* + * camss_link_entities - Register subdev nodes and create links * @camss: CAMSS device * * Return 0 on success or a negative error code on failure */ -static int camss_register_entities(struct camss *camss) +static int camss_link_entities(struct camss *camss) { int i, j, k; int ret; for (i = 0; i < camss->res->csiphy_num; i++) { - ret = msm_csiphy_register_entity(&camss->csiphy[i], - &camss->v4l2_dev); - if (ret < 0) { - dev_err(camss->dev, - "Failed to register csiphy%d entity: %d\n", - i, ret); - goto err_reg_csiphy; - } - } - - for (i = 0; i < camss->res->csid_num; i++) { - ret = msm_csid_register_entity(&camss->csid[i], - &camss->v4l2_dev); - if (ret < 0) { - dev_err(camss->dev, - "Failed to register csid%d entity: %d\n", - i, ret); - goto err_reg_csid; - } - } - - ret = msm_ispif_register_entities(camss->ispif, - &camss->v4l2_dev); - if (ret < 0) { - dev_err(camss->dev, "Failed to register ispif entities: %d\n", - ret); - goto err_reg_ispif; - } - - for (i = 0; i < camss->res->vfe_num; i++) { - ret = msm_vfe_register_entities(&camss->vfe[i], - &camss->v4l2_dev); - if (ret < 0) { - dev_err(camss->dev, - "Failed to register vfe%d entities: %d\n", - i, ret); - goto err_reg_vfe; - } - } - - for (i = 0; i < camss->res->csiphy_num; i++) { for (j = 0; j < camss->res->csid_num; j++) { - ret = media_create_pad_link( - &camss->csiphy[i].subdev.entity, - MSM_CSIPHY_PAD_SRC, - &camss->csid[j].subdev.entity, - MSM_CSID_PAD_SINK, - 0); + ret = media_create_pad_link(&camss->csiphy[i].subdev.entity, + MSM_CSIPHY_PAD_SRC, + &camss->csid[j].subdev.entity, + MSM_CSID_PAD_SINK, + 0); if (ret < 0) { - dev_err(camss->dev, - "Failed to link %s->%s entities: %d\n", - camss->csiphy[i].subdev.entity.name, - camss->csid[j].subdev.entity.name, - ret); - goto err_link; + camss_link_err(camss, + camss->csiphy[i].subdev.entity.name, + camss->csid[j].subdev.entity.name, + ret); + return ret; } } } @@ -1317,26 +2346,24 @@ static int camss_register_entities(struct camss *camss) if (camss->ispif) { for (i = 0; i < camss->res->csid_num; i++) { for (j = 0; j < camss->ispif->line_num; j++) { - ret = media_create_pad_link( - &camss->csid[i].subdev.entity, - MSM_CSID_PAD_SRC, - &camss->ispif->line[j].subdev.entity, - MSM_ISPIF_PAD_SINK, - 0); + ret = media_create_pad_link(&camss->csid[i].subdev.entity, + MSM_CSID_PAD_SRC, + &camss->ispif->line[j].subdev.entity, + MSM_ISPIF_PAD_SINK, + 0); if (ret < 0) { - dev_err(camss->dev, - "Failed to link %s->%s entities: %d\n", - camss->csid[i].subdev.entity.name, - camss->ispif->line[j].subdev.entity.name, - ret); - goto err_link; + camss_link_err(camss, + camss->csid[i].subdev.entity.name, + camss->ispif->line[j].subdev.entity.name, + ret); + return ret; } } } for (i = 0; i < camss->ispif->line_num; i++) for (k = 0; k < camss->res->vfe_num; k++) - for (j = 0; j < camss->vfe[k].line_num; j++) { + for (j = 0; j < camss->vfe[k].res->line_num; j++) { struct v4l2_subdev *ispif = &camss->ispif->line[i].subdev; struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev; @@ -1346,18 +2373,16 @@ static int camss_register_entities(struct camss *camss) MSM_VFE_PAD_SINK, 0); if (ret < 0) { - dev_err(camss->dev, - "Failed to link %s->%s entities: %d\n", - ispif->entity.name, - vfe->entity.name, - ret); - goto err_link; + camss_link_err(camss, ispif->entity.name, + vfe->entity.name, + ret); + return ret; } } } else { for (i = 0; i < camss->res->csid_num; i++) for (k = 0; k < camss->res->vfe_num; k++) - for (j = 0; j < camss->vfe[k].line_num; j++) { + for (j = 0; j < camss->vfe[k].res->line_num; j++) { struct v4l2_subdev *csid = &camss->csid[i].subdev; struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev; @@ -1367,20 +2392,70 @@ static int camss_register_entities(struct camss *camss) MSM_VFE_PAD_SINK, 0); if (ret < 0) { - dev_err(camss->dev, - "Failed to link %s->%s entities: %d\n", - csid->entity.name, - vfe->entity.name, - ret); - goto err_link; + camss_link_err(camss, csid->entity.name, + vfe->entity.name, + ret); + return ret; } } } return 0; +} + +/* + * camss_register_entities - Register subdev nodes and create links + * @camss: CAMSS device + * + * Return 0 on success or a negative error code on failure + */ +static int camss_register_entities(struct camss *camss) +{ + int i; + int ret; + + for (i = 0; i < camss->res->csiphy_num; i++) { + ret = msm_csiphy_register_entity(&camss->csiphy[i], + &camss->v4l2_dev); + if (ret < 0) { + dev_err(camss->dev, + "Failed to register csiphy%d entity: %d\n", + i, ret); + goto err_reg_csiphy; + } + } + + for (i = 0; i < camss->res->csid_num; i++) { + ret = msm_csid_register_entity(&camss->csid[i], + &camss->v4l2_dev); + if (ret < 0) { + dev_err(camss->dev, + "Failed to register csid%d entity: %d\n", + i, ret); + goto err_reg_csid; + } + } + + ret = msm_ispif_register_entities(camss->ispif, + &camss->v4l2_dev); + if (ret < 0) { + dev_err(camss->dev, "Failed to register ispif entities: %d\n", ret); + goto err_reg_ispif; + } + + for (i = 0; i < camss->res->vfe_num; i++) { + ret = msm_vfe_register_entities(&camss->vfe[i], + &camss->v4l2_dev); + if (ret < 0) { + dev_err(camss->dev, + "Failed to register vfe%d entities: %d\n", + i, ret); + goto err_reg_vfe; + } + } + + return 0; -err_link: - i = camss->res->vfe_num; err_reg_vfe: for (i--; i >= 0; i--) msm_vfe_unregister_entities(&camss->vfe[i]); @@ -1468,9 +2543,9 @@ static int camss_subdev_notifier_complete(struct v4l2_async_notifier *async) input, MSM_CSIPHY_PAD_SINK, MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); if (ret < 0) { - dev_err(camss->dev, - "Failed to link %s->%s entities: %d\n", - sensor->name, input->name, ret); + camss_link_err(camss, sensor->name, + input->name, + ret); return ret; } } @@ -1518,7 +2593,7 @@ static int camss_configure_pd(struct camss *camss) /* count the # of VFEs which have flagged power-domain */ for (vfepd_num = i = 0; i < camss->res->vfe_num; i++) { - if (res->vfe_res[i].has_pd) + if (res->vfe_res[i].vfe.has_pd) vfepd_num++; } @@ -1537,10 +2612,8 @@ static int camss_configure_pd(struct camss *camss) if (camss->res->pd_name) { camss->genpd = dev_pm_domain_attach_by_name(camss->dev, camss->res->pd_name); - if (IS_ERR(camss->genpd)) { - ret = PTR_ERR(camss->genpd); - goto fail_pm; - } + if (IS_ERR(camss->genpd)) + return PTR_ERR(camss->genpd); } if (!camss->genpd) { @@ -1550,14 +2623,13 @@ static int camss_configure_pd(struct camss *camss) */ camss->genpd = dev_pm_domain_attach_by_id(camss->dev, camss->genpd_num - 1); + if (IS_ERR(camss->genpd)) + return PTR_ERR(camss->genpd); } - if (IS_ERR_OR_NULL(camss->genpd)) { - if (!camss->genpd) - ret = -ENODEV; - else - ret = PTR_ERR(camss->genpd); - goto fail_pm; - } + + if (!camss->genpd) + return -ENODEV; + camss->genpd_link = device_link_add(camss->dev, camss->genpd, DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE); @@ -1646,6 +2718,7 @@ static int camss_probe(struct platform_device *pdev) return -ENOMEM; if (camss->res->version == CAMSS_8x16 || + camss->res->version == CAMSS_8x53 || camss->res->version == CAMSS_8x96) { camss->ispif = devm_kcalloc(dev, 1, sizeof(*camss->ispif), GFP_KERNEL); if (!camss->ispif) @@ -1690,6 +2763,8 @@ static int camss_probe(struct platform_device *pdev) v4l2_async_nf_init(&camss->notifier, &camss->v4l2_dev); + pm_runtime_enable(dev); + num_subdevs = camss_of_parse_ports(camss); if (num_subdevs < 0) { ret = num_subdevs; @@ -1700,6 +2775,10 @@ static int camss_probe(struct platform_device *pdev) if (ret < 0) goto err_v4l2_device_unregister; + ret = camss->res->link_entities(camss); + if (ret < 0) + goto err_register_subdevs; + if (num_subdevs) { camss->notifier.ops = &camss_subdev_notifier_ops; @@ -1726,8 +2805,6 @@ static int camss_probe(struct platform_device *pdev) } } - pm_runtime_enable(dev); - return 0; err_register_subdevs: @@ -1735,6 +2812,7 @@ err_register_subdevs: err_v4l2_device_unregister: v4l2_device_unregister(&camss->v4l2_dev); v4l2_async_nf_cleanup(&camss->notifier); + pm_runtime_disable(dev); err_genpd_cleanup: camss_genpd_cleanup(camss); @@ -1779,6 +2857,21 @@ static const struct camss_resources msm8916_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8x16), .csid_num = ARRAY_SIZE(csid_res_8x16), .vfe_num = ARRAY_SIZE(vfe_res_8x16), + .link_entities = camss_link_entities +}; + +static const struct camss_resources msm8953_resources = { + .version = CAMSS_8x53, + .icc_res = icc_res_8x53, + .icc_path_num = ARRAY_SIZE(icc_res_8x53), + .csiphy_res = csiphy_res_8x96, + .csid_res = csid_res_8x53, + .ispif_res = &ispif_res_8x53, + .vfe_res = vfe_res_8x53, + .csiphy_num = ARRAY_SIZE(csiphy_res_8x96), + .csid_num = ARRAY_SIZE(csid_res_8x53), + .vfe_num = ARRAY_SIZE(vfe_res_8x53), + .link_entities = camss_link_entities }; static const struct camss_resources msm8996_resources = { @@ -1790,6 +2883,7 @@ static const struct camss_resources msm8996_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8x96), .csid_num = ARRAY_SIZE(csid_res_8x96), .vfe_num = ARRAY_SIZE(vfe_res_8x96), + .link_entities = camss_link_entities }; static const struct camss_resources sdm660_resources = { @@ -1801,6 +2895,7 @@ static const struct camss_resources sdm660_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_660), .csid_num = ARRAY_SIZE(csid_res_660), .vfe_num = ARRAY_SIZE(vfe_res_660), + .link_entities = camss_link_entities }; static const struct camss_resources sdm845_resources = { @@ -1811,6 +2906,7 @@ static const struct camss_resources sdm845_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_845), .csid_num = ARRAY_SIZE(csid_res_845), .vfe_num = ARRAY_SIZE(vfe_res_845), + .link_entities = camss_link_entities }; static const struct camss_resources sm8250_resources = { @@ -1824,11 +2920,44 @@ static const struct camss_resources sm8250_resources = { .csiphy_num = ARRAY_SIZE(csiphy_res_8250), .csid_num = ARRAY_SIZE(csid_res_8250), .vfe_num = ARRAY_SIZE(vfe_res_8250), + .link_entities = camss_link_entities +}; + +static const struct camss_resources sc8280xp_resources = { + .version = CAMSS_8280XP, + .pd_name = "top", + .csiphy_res = csiphy_res_sc8280xp, + .csid_res = csid_res_sc8280xp, + .ispif_res = NULL, + .vfe_res = vfe_res_sc8280xp, + .icc_res = icc_res_sc8280xp, + .icc_path_num = ARRAY_SIZE(icc_res_sc8280xp), + .csiphy_num = ARRAY_SIZE(csiphy_res_sc8280xp), + .csid_num = ARRAY_SIZE(csid_res_sc8280xp), + .vfe_num = ARRAY_SIZE(vfe_res_sc8280xp), + .link_entities = camss_link_entities +}; + +static const struct camss_resources sc7280_resources = { + .version = CAMSS_7280, + .pd_name = "top", + .csiphy_res = csiphy_res_7280, + .csid_res = csid_res_7280, + .vfe_res = vfe_res_7280, + .icc_res = icc_res_sc7280, + .icc_path_num = ARRAY_SIZE(icc_res_sc7280), + .csiphy_num = ARRAY_SIZE(csiphy_res_7280), + .csid_num = ARRAY_SIZE(csid_res_7280), + .vfe_num = ARRAY_SIZE(vfe_res_7280), + .link_entities = camss_link_entities }; static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, + { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, { .compatible = "qcom,msm8996-camss", .data = &msm8996_resources }, + { .compatible = "qcom,sc7280-camss", .data = &sc7280_resources }, + { .compatible = "qcom,sc8280xp-camss", .data = &sc8280xp_resources }, { .compatible = "qcom,sdm660-camss", .data = &sdm660_resources }, { .compatible = "qcom,sdm845-camss", .data = &sdm845_resources }, { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources }, @@ -1878,7 +3007,7 @@ static const struct dev_pm_ops camss_pm_ops = { static struct platform_driver qcom_camss_driver = { .probe = camss_probe, - .remove_new = camss_remove, + .remove = camss_remove, .driver = { .name = "qcom-camss", .of_match_table = camss_dt_match, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index a0c2dcc779f0..9a046eea334f 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -22,6 +22,7 @@ #include "camss-csiphy.h" #include "camss-ispif.h" #include "camss-vfe.h" +#include "camss-format.h" #define to_camss(ptr_module) \ container_of(ptr_module, struct camss, ptr_module) @@ -48,11 +49,11 @@ struct camss_subdev_resources { u32 clock_rate[CAMSS_RES_MAX][CAMSS_RES_MAX]; char *reg[CAMSS_RES_MAX]; char *interrupt[CAMSS_RES_MAX]; - char *pd_name; - u8 line_num; - bool has_pd; - bool is_lite; - const void *ops; + union { + struct csiphy_subdev_resources csiphy; + struct csid_subdev_resources csid; + struct vfe_subdev_resources vfe; + }; }; struct icc_bw_tbl { @@ -65,6 +66,10 @@ struct resources_icc { struct icc_bw_tbl icc_bw_tbl; }; +struct resources_wrapper { + char *reg; +}; + enum pm_domain { PM_DOMAIN_VFE0 = 0, PM_DOMAIN_VFE1 = 1, @@ -72,11 +77,14 @@ enum pm_domain { }; enum camss_version { + CAMSS_660, + CAMSS_7280, CAMSS_8x16, + CAMSS_8x53, CAMSS_8x96, - CAMSS_660, - CAMSS_845, CAMSS_8250, + CAMSS_8280XP, + CAMSS_845, }; enum icc_count { @@ -91,11 +99,13 @@ struct camss_resources { const struct camss_subdev_resources *csid_res; const struct camss_subdev_resources *ispif_res; const struct camss_subdev_resources *vfe_res; + const struct resources_wrapper *csid_wrapper_res; const struct resources_icc *icc_res; const unsigned int icc_path_num; const unsigned int csiphy_num; const unsigned int csid_num; const unsigned int vfe_num; + int (*link_entities)(struct camss *camss); }; struct camss { @@ -107,6 +117,7 @@ struct camss { struct csid_device *csid; struct ispif_device *ispif; struct vfe_device *vfe; + void __iomem *csid_wrapper_base; atomic_t ref_count; int genpd_num; struct device *genpd; @@ -132,6 +143,12 @@ struct camss_clock { u32 nfreqs; }; +struct parent_dev_ops { + int (*get)(struct camss *camss, int id); + int (*put)(struct camss *camss, int id); + void __iomem *(*get_base_address)(struct camss *camss, int id); +}; + void camss_add_clock_margin(u64 *rate); int camss_enable_clocks(int nclocks, struct camss_clock *clock, struct device *dev); @@ -142,6 +159,8 @@ s64 camss_get_link_freq(struct media_entity *entity, unsigned int bpp, int camss_get_pixel_clock(struct media_entity *entity, u64 *pixel_clock); int camss_pm_domain_on(struct camss *camss, int id); void camss_pm_domain_off(struct camss *camss, int id); +int camss_vfe_get(struct camss *camss, int id); +void camss_vfe_put(struct camss *camss, int id); void camss_delete(struct camss *camss); #endif /* QC_MSM_CAMSS_H */ diff --git a/drivers/media/platform/qcom/venus/Kconfig b/drivers/media/platform/qcom/venus/Kconfig index bfd50e8f3421..bc2e410b29cb 100644 --- a/drivers/media/platform/qcom/venus/Kconfig +++ b/drivers/media/platform/qcom/venus/Kconfig @@ -3,6 +3,7 @@ config VIDEO_QCOM_VENUS depends on V4L_MEM2MEM_DRIVERS depends on VIDEO_DEV && QCOM_SMEM depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST + select OF_DYNAMIC if ARCH_QCOM select QCOM_MDT_LOADER if ARCH_QCOM select QCOM_SCM select VIDEOBUF2_DMA_CONTIG diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index a712dd4f02a5..77d48578ecd2 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -16,8 +16,10 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/types.h> +#include <linux/pm_domain.h> #include <linux/pm_runtime.h> #include <media/videobuf2-v4l2.h> +#include <media/v4l2-ctrls.h> #include <media/v4l2-mem2mem.h> #include <media/v4l2-ioctl.h> @@ -67,6 +69,7 @@ static void venus_event_notify(struct venus_core *core, u32 event) mutex_lock(&core->lock); set_bit(0, &core->sys_error); + set_bit(0, &core->dump_core); list_for_each_entry(inst, &core->instances, list) inst->ops->event_notify(inst, EVT_SESSION_ERROR, NULL); mutex_unlock(&core->lock); @@ -109,12 +112,16 @@ static void venus_sys_error_handler(struct work_struct *work) venus_shutdown(core); - venus_coredump(core); + if (test_bit(0, &core->dump_core)) { + venus_coredump(core); + clear_bit(0, &core->dump_core); + } pm_runtime_put_sync(core->dev); for (i = 0; i < max_attempts; i++) { - if (!core->pmdomains[0] || !pm_runtime_active(core->pmdomains[0])) + if (!core->pmdomains || + !pm_runtime_active(core->pmdomains->pd_devs[0])) break; usleep_range(1000, 1500); } @@ -279,6 +286,89 @@ static irqreturn_t venus_isr_thread(int irq, void *dev_id) return ret; } +#if defined(CONFIG_OF_DYNAMIC) +static int venus_add_video_core(struct venus_core *core, const char *node_name, + const char *compat) +{ + struct of_changeset *ocs = core->ocs; + struct device *dev = core->dev; + struct device_node *np, *enp; + int ret; + + if (!node_name) + return 0; + + enp = of_find_node_by_name(dev->of_node, node_name); + if (enp) { + of_node_put(enp); + return 0; + } + + np = of_changeset_create_node(ocs, dev->of_node, node_name); + if (!np) { + dev_err(dev, "Unable to create new node\n"); + return -ENODEV; + } + + ret = of_changeset_add_prop_string(ocs, np, "compatible", compat); + if (ret) + dev_err(dev, "unable to add %s\n", compat); + + of_node_put(np); + + return ret; +} + +static int venus_add_dynamic_nodes(struct venus_core *core) +{ + struct device *dev = core->dev; + int ret; + + core->ocs = kmalloc(sizeof(*core->ocs), GFP_KERNEL); + if (!core->ocs) + return -ENOMEM; + + of_changeset_init(core->ocs); + + ret = venus_add_video_core(core, core->res->dec_nodename, "venus-decoder"); + if (ret) + goto err; + + ret = venus_add_video_core(core, core->res->enc_nodename, "venus-encoder"); + if (ret) + goto err; + + ret = of_changeset_apply(core->ocs); + if (ret) { + dev_err(dev, "applying changeset fail ret %d\n", ret); + goto err; + } + + return 0; +err: + of_changeset_destroy(core->ocs); + kfree(core->ocs); + core->ocs = NULL; + return ret; +} + +static void venus_remove_dynamic_nodes(struct venus_core *core) +{ + if (core->ocs) { + of_changeset_revert(core->ocs); + of_changeset_destroy(core->ocs); + kfree(core->ocs); + } +} +#else +static int venus_add_dynamic_nodes(struct venus_core *core) +{ + return 0; +} + +static void venus_remove_dynamic_nodes(struct venus_core *core) {} +#endif + static int venus_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -358,9 +448,15 @@ static int venus_probe(struct platform_device *pdev) if (ret < 0) goto err_runtime_disable; + if (core->res->dec_nodename || core->res->enc_nodename) { + ret = venus_add_dynamic_nodes(core); + if (ret) + goto err_runtime_disable; + } + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); if (ret) - goto err_runtime_disable; + goto err_remove_dynamic_nodes; ret = venus_firmware_init(core); if (ret) @@ -404,10 +500,12 @@ err_firmware_deinit: venus_firmware_deinit(core); err_of_depopulate: of_platform_depopulate(dev); +err_remove_dynamic_nodes: + venus_remove_dynamic_nodes(core); err_runtime_disable: pm_runtime_put_noidle(dev); - pm_runtime_set_suspended(dev); pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); hfi_destroy(core); err_core_deinit: hfi_core_deinit(core, false); @@ -424,6 +522,7 @@ static void venus_remove(struct platform_device *pdev) struct device *dev = core->dev; int ret; + cancel_delayed_work_sync(&core->work); ret = pm_runtime_get_sync(dev); WARN_ON(ret < 0); @@ -435,6 +534,8 @@ static void venus_remove(struct platform_device *pdev) venus_firmware_deinit(core); + venus_remove_dynamic_nodes(core); + pm_runtime_put_sync(dev); pm_runtime_disable(dev); @@ -495,6 +596,26 @@ err_cpucfg_path: return ret; } +void venus_close_common(struct venus_inst *inst) +{ + /* + * Make sure we don't have IRQ/IRQ-thread currently running + * or pending execution, which would race with the inst destruction. + */ + synchronize_irq(inst->core->irq); + + v4l2_m2m_ctx_release(inst->m2m_ctx); + v4l2_m2m_release(inst->m2m_dev); + hfi_session_destroy(inst); + v4l2_fh_del(&inst->fh); + v4l2_fh_exit(&inst->fh); + v4l2_ctrl_handler_free(&inst->ctrl_handler); + + mutex_destroy(&inst->lock); + mutex_destroy(&inst->ctx_q_lock); +} +EXPORT_SYMBOL_GPL(venus_close_common); + static __maybe_unused int venus_runtime_resume(struct device *dev) { struct venus_core *core = dev_get_drvdata(dev); @@ -550,6 +671,8 @@ static const struct venus_resources msm8916_res = { .vmem_addr = 0, .dma_mask = 0xddc00000 - 1, .fwname = "qcom/venus-1.8/venus.mbn", + .dec_nodename = "video-decoder", + .enc_nodename = "video-encoder", }; static const struct freq_tbl msm8996_freq_table[] = { @@ -585,6 +708,44 @@ static const struct venus_resources msm8996_res = { .fwname = "qcom/venus-4.2/venus.mbn", }; +static const struct freq_tbl msm8998_freq_table[] = { + { 1944000, 465000000 }, /* 4k UHD @ 60 (decode only) */ + { 972000, 465000000 }, /* 4k UHD @ 30 */ + { 489600, 360000000 }, /* 1080p @ 60 */ + { 244800, 186000000 }, /* 1080p @ 30 */ + { 108000, 100000000 }, /* 720p @ 30 */ +}; + +static const struct reg_val msm8998_reg_preset[] = { + { 0x80124, 0x00000003 }, + { 0x80550, 0x01111111 }, + { 0x80560, 0x01111111 }, + { 0x80568, 0x01111111 }, + { 0x80570, 0x01111111 }, + { 0x80580, 0x01111111 }, + { 0x80588, 0x01111111 }, + { 0xe2010, 0x00000000 }, +}; + +static const struct venus_resources msm8998_res = { + .freq_tbl = msm8998_freq_table, + .freq_tbl_size = ARRAY_SIZE(msm8998_freq_table), + .reg_tbl = msm8998_reg_preset, + .reg_tbl_size = ARRAY_SIZE(msm8998_reg_preset), + .clks = { "core", "iface", "bus", "mbus" }, + .clks_num = 4, + .vcodec0_clks = { "core" }, + .vcodec1_clks = { "core" }, + .vcodec_clks_num = 1, + .max_load = 2563200, + .hfi_version = HFI_VERSION_3XX, + .vmem_id = VIDC_RESOURCE_NONE, + .vmem_size = 0, + .vmem_addr = 0, + .dma_mask = 0xddc00000 - 1, + .fwname = "qcom/venus-4.4/venus.mbn", +}; + static const struct freq_tbl sdm660_freq_table[] = { { 979200, 518400000 }, { 489600, 441600000 }, @@ -705,9 +866,9 @@ static const struct venus_resources sdm845_res_v2 = { .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, .vcodec1_clks = { "vcodec1_core", "vcodec1_bus" }, .vcodec_clks_num = 2, - .vcodec_pmdomains = { "venus", "vcodec0", "vcodec1" }, + .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0", "vcodec1" }, .vcodec_pmdomains_num = 3, - .opp_pmdomain = (const char *[]) { "cx", NULL }, + .opp_pmdomain = (const char *[]) { "cx" }, .vcodec_num = 2, .max_load = 3110400, /* 4096x2160@90 */ .hfi_version = HFI_VERSION_4XX, @@ -721,6 +882,8 @@ static const struct venus_resources sdm845_res_v2 = { .cp_nonpixel_start = 0x1000000, .cp_nonpixel_size = 0x24800000, .fwname = "qcom/venus-5.2/venus.mbn", + .dec_nodename = "video-core0", + .enc_nodename = "video-core1", }; static const struct freq_tbl sc7180_freq_table[] = { @@ -754,9 +917,9 @@ static const struct venus_resources sc7180_res = { .clks_num = 3, .vcodec0_clks = { "vcodec0_core", "vcodec0_bus" }, .vcodec_clks_num = 2, - .vcodec_pmdomains = { "venus", "vcodec0" }, + .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" }, .vcodec_pmdomains_num = 2, - .opp_pmdomain = (const char *[]) { "cx", NULL }, + .opp_pmdomain = (const char *[]) { "cx" }, .vcodec_num = 1, .hfi_version = HFI_VERSION_4XX, .vpu_version = VPU_VERSION_AR50, @@ -769,6 +932,8 @@ static const struct venus_resources sc7180_res = { .cp_nonpixel_start = 0x1000000, .cp_nonpixel_size = 0x24800000, .fwname = "qcom/venus-5.4/venus.mbn", + .dec_nodename = "video-decoder", + .enc_nodename = "video-encoder", }; static const struct freq_tbl sm8250_freq_table[] = { @@ -811,9 +976,9 @@ static const struct venus_resources sm8250_res = { .resets_num = 2, .vcodec0_clks = { "vcodec0_core" }, .vcodec_clks_num = 1, - .vcodec_pmdomains = { "venus", "vcodec0" }, + .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" }, .vcodec_pmdomains_num = 2, - .opp_pmdomain = (const char *[]) { "mx", NULL }, + .opp_pmdomain = (const char *[]) { "mx" }, .vcodec_num = 1, .max_load = 7833600, .hfi_version = HFI_VERSION_6XX, @@ -824,6 +989,8 @@ static const struct venus_resources sm8250_res = { .vmem_addr = 0, .dma_mask = 0xe0000000 - 1, .fwname = "qcom/vpu-1.0/venus.mbn", + .dec_nodename = "video-decoder", + .enc_nodename = "video-encoder", }; static const struct freq_tbl sc7280_freq_table[] = { @@ -870,9 +1037,9 @@ static const struct venus_resources sc7280_res = { .clks_num = 3, .vcodec0_clks = {"vcodec_core", "vcodec_bus"}, .vcodec_clks_num = 2, - .vcodec_pmdomains = { "venus", "vcodec0" }, + .vcodec_pmdomains = (const char *[]) { "venus", "vcodec0" }, .vcodec_pmdomains_num = 2, - .opp_pmdomain = (const char *[]) { "cx", NULL }, + .opp_pmdomain = (const char *[]) { "cx" }, .vcodec_num = 1, .hfi_version = HFI_VERSION_6XX, .vpu_version = VPU_VERSION_IRIS2_1, @@ -886,11 +1053,14 @@ static const struct venus_resources sc7280_res = { .cp_nonpixel_start = 0x1000000, .cp_nonpixel_size = 0x24800000, .fwname = "qcom/vpu-2.0/venus.mbn", + .dec_nodename = "video-decoder", + .enc_nodename = "video-encoder", }; static const struct of_device_id venus_dt_match[] = { { .compatible = "qcom,msm8916-venus", .data = &msm8916_res, }, { .compatible = "qcom,msm8996-venus", .data = &msm8996_res, }, + { .compatible = "qcom,msm8998-venus", .data = &msm8998_res, }, { .compatible = "qcom,sdm660-venus", .data = &sdm660_res, }, { .compatible = "qcom,sdm845-venus", .data = &sdm845_res, }, { .compatible = "qcom,sdm845-venus-v2", .data = &sdm845_res_v2, }, @@ -903,7 +1073,7 @@ MODULE_DEVICE_TABLE(of, venus_dt_match); static struct platform_driver qcom_venus_driver = { .probe = venus_probe, - .remove_new = venus_remove, + .remove = venus_remove, .driver = { .name = "qcom-venus", .of_match_table = venus_dt_match, diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index 4a633261ece4..abeeafa86697 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -25,8 +25,8 @@ #define VIDC_CLKS_NUM_MAX 4 #define VIDC_VCODEC_CLKS_NUM_MAX 2 -#define VIDC_PMDOMAINS_NUM_MAX 3 #define VIDC_RESETS_NUM_MAX 2 +#define VIDC_MAX_HIER_CODING_LAYER 6 extern int venus_fw_debug; @@ -72,7 +72,7 @@ struct venus_resources { const char * const vcodec0_clks[VIDC_VCODEC_CLKS_NUM_MAX]; const char * const vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX]; unsigned int vcodec_clks_num; - const char * const vcodec_pmdomains[VIDC_PMDOMAINS_NUM_MAX]; + const char **vcodec_pmdomains; unsigned int vcodec_pmdomains_num; const char **opp_pmdomain; unsigned int vcodec_num; @@ -90,6 +90,8 @@ struct venus_resources { u32 cp_nonpixel_start; u32 cp_nonpixel_size; const char *fwname; + const char *enc_nodename; + const char *dec_nodename; }; enum venus_fmt { @@ -133,9 +135,7 @@ struct venus_format { * @vcodec1_clks: an array of vcodec1 struct clk pointers * @video_path: an interconnect handle to video to/from memory path * @cpucfg_path: an interconnect handle to cpu configuration path - * @has_opp_table: does OPP table exist - * @pmdomains: an array of pmdomains struct device pointers - * @opp_dl_venus: an device-link for device OPP + * @pmdomains: a pointer to a list of pmdomains * @opp_pmdomain: an OPP power-domain * @resets: an array of reset signals * @vdev_dec: a reference to video device structure for decoder instances @@ -170,6 +170,8 @@ struct venus_format { * @core1_usage_count: usage counter for core1 * @root: debugfs root directory * @venus_ver: the venus firmware version + * @dump_core: a flag indicating that a core dump is required + * @ocs: OF changeset pointer */ struct venus_core { void __iomem *base; @@ -186,10 +188,8 @@ struct venus_core { struct clk *vcodec1_clks[VIDC_VCODEC_CLKS_NUM_MAX]; struct icc_path *video_path; struct icc_path *cpucfg_path; - bool has_opp_table; - struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX]; - struct device_link *opp_dl_venus; - struct device *opp_pmdomain; + struct dev_pm_domain_list *pmdomains; + struct dev_pm_domain_list *opp_pmdomain; struct reset_control *resets[VIDC_RESETS_NUM_MAX]; struct video_device *vdev_dec; struct video_device *vdev_enc; @@ -233,6 +233,8 @@ struct venus_core { u32 minor; u32 rev; } venus_ver; + unsigned long dump_core; + struct of_changeset *ocs; }; struct vdec_controls { @@ -254,6 +256,7 @@ struct venc_controls { u32 rc_enable; u32 const_quality; u32 frame_skip_mode; + u32 layer_bitrate; u32 h264_i_period; u32 h264_entropy_mode; @@ -272,6 +275,8 @@ struct venc_controls { s32 h264_loop_filter_alpha; s32 h264_loop_filter_beta; u32 h264_8x8_transform; + u32 h264_hier_layers; + u32 h264_hier_layer_bitrate[VIDC_MAX_HIER_CODING_LAYER]; u32 hevc_i_qp; u32 hevc_p_qp; @@ -428,7 +433,6 @@ enum venus_inst_modes { * @error: an error returned during last HFI sync operation * @session_error: a flag rised by HFI interface in case of session error * @ops: HFI operations - * @priv: a private for HFI operations callbacks * @session_type: the type of the session (decoder or encoder) * @hprop: a union used as a holder by get property * @core_acquired: the Core has been acquired @@ -564,4 +568,6 @@ is_fw_rev_or_older(struct venus_core *core, u32 vmajor, u32 vminor, u32 vrev) (core)->venus_ver.minor == vminor && (core)->venus_ver.rev <= vrev); } + +void venus_close_common(struct venus_inst *inst); #endif diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index fe7da2b30482..66a18830e66d 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -316,10 +316,10 @@ int venus_firmware_init(struct venus_core *core) core->fw.dev = &pdev->dev; - iommu_dom = iommu_domain_alloc(&platform_bus_type); - if (!iommu_dom) { + iommu_dom = iommu_paging_domain_alloc(core->fw.dev); + if (IS_ERR(iommu_dom)) { dev_err(core->fw.dev, "Failed to allocate iommu domain\n"); - ret = -ENOMEM; + ret = PTR_ERR(iommu_dom); goto err_unregister; } diff --git a/drivers/media/platform/qcom/venus/hfi.c b/drivers/media/platform/qcom/venus/hfi.c index e00aedb41d16..675e6fd1e9fa 100644 --- a/drivers/media/platform/qcom/venus/hfi.c +++ b/drivers/media/platform/qcom/venus/hfi.c @@ -138,29 +138,6 @@ int hfi_core_trigger_ssr(struct venus_core *core, u32 type) return core->ops->core_trigger_ssr(core, type); } -int hfi_core_ping(struct venus_core *core) -{ - int ret; - - mutex_lock(&core->lock); - - ret = core->ops->core_ping(core, 0xbeef); - if (ret) - goto unlock; - - ret = wait_for_completion_timeout(&core->done, TIMEOUT); - if (!ret) { - ret = -ETIMEDOUT; - goto unlock; - } - ret = 0; - if (core->error != HFI_ERR_NONE) - ret = -ENODEV; -unlock: - mutex_unlock(&core->lock); - return ret; -} - static int wait_session_msg(struct venus_inst *inst) { int ret; diff --git a/drivers/media/platform/qcom/venus/hfi.h b/drivers/media/platform/qcom/venus/hfi.h index f25d412d6553..0338841d5992 100644 --- a/drivers/media/platform/qcom/venus/hfi.h +++ b/drivers/media/platform/qcom/venus/hfi.h @@ -108,7 +108,6 @@ struct hfi_inst_ops { struct hfi_ops { int (*core_init)(struct venus_core *core); int (*core_deinit)(struct venus_core *core); - int (*core_ping)(struct venus_core *core, u32 cookie); int (*core_trigger_ssr)(struct venus_core *core, u32 trigger_type); int (*session_init)(struct venus_inst *inst, u32 session_type, @@ -152,7 +151,6 @@ int hfi_core_deinit(struct venus_core *core, bool blocking); int hfi_core_suspend(struct venus_core *core); int hfi_core_resume(struct venus_core *core, bool force); int hfi_core_trigger_ssr(struct venus_core *core, u32 type); -int hfi_core_ping(struct venus_core *core); int hfi_session_create(struct venus_inst *inst, const struct hfi_inst_ops *ops); void hfi_session_destroy(struct venus_inst *inst); int hfi_session_init(struct venus_inst *inst, u32 pixfmt); diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c b/drivers/media/platform/qcom/venus/hfi_cmds.c index 3418d2dd9371..3ae063094e3e 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.c +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c @@ -156,7 +156,7 @@ void pkt_sys_image_version(struct hfi_sys_get_property_pkt *pkt) pkt->hdr.size = sizeof(*pkt); pkt->hdr.pkt_type = HFI_CMD_SYS_GET_PROPERTY; pkt->num_properties = 1; - pkt->data[0] = HFI_PROPERTY_SYS_IMAGE_VERSION; + pkt->data = HFI_PROPERTY_SYS_IMAGE_VERSION; } int pkt_session_init(struct hfi_session_init_pkt *pkt, void *cookie, @@ -331,7 +331,7 @@ int pkt_session_ftb(struct hfi_session_fill_buffer_pkt *pkt, void *cookie, pkt->alloc_len = out_frame->alloc_len; pkt->filled_len = out_frame->filled_len; pkt->offset = out_frame->offset; - pkt->data[0] = out_frame->extradata_size; + pkt->data = out_frame->extradata_size; return 0; } @@ -402,7 +402,7 @@ static int pkt_session_get_property_1x(struct hfi_session_get_property_pkt *pkt, pkt->shdr.hdr.pkt_type = HFI_CMD_SESSION_GET_PROPERTY; pkt->shdr.session_id = hash32_ptr(cookie); pkt->num_properties = 1; - pkt->data[0] = ptype; + pkt->data = ptype; return 0; } @@ -1110,7 +1110,7 @@ pkt_session_get_property_3xx(struct hfi_session_get_property_pkt *pkt, switch (ptype) { case HFI_PROPERTY_CONFIG_VDEC_ENTROPY: - pkt->data[0] = HFI_PROPERTY_CONFIG_VDEC_ENTROPY; + pkt->data = HFI_PROPERTY_CONFIG_VDEC_ENTROPY; break; default: ret = pkt_session_get_property_1x(pkt, cookie, ptype); diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.h b/drivers/media/platform/qcom/venus/hfi_cmds.h index 20acd412ee7b..a83125bc17aa 100644 --- a/drivers/media/platform/qcom/venus/hfi_cmds.h +++ b/drivers/media/platform/qcom/venus/hfi_cmds.h @@ -74,7 +74,7 @@ struct hfi_sys_set_property_pkt { struct hfi_sys_get_property_pkt { struct hfi_pkt_hdr hdr; u32 num_properties; - u32 data[1]; + u32 data; }; struct hfi_sys_set_buffers_pkt { @@ -82,7 +82,7 @@ struct hfi_sys_set_buffers_pkt { u32 buffer_type; u32 buffer_size; u32 num_buffers; - u32 buffer_addr[1]; + u32 buffer_addr[]; }; struct hfi_sys_ping_pkt { @@ -151,7 +151,7 @@ struct hfi_session_empty_buffer_compressed_pkt { u32 input_tag; u32 packet_buffer; u32 extradata_buffer; - u32 data[1]; + u32 data; }; struct hfi_session_empty_buffer_uncompressed_plane0_pkt { @@ -168,7 +168,7 @@ struct hfi_session_empty_buffer_uncompressed_plane0_pkt { u32 input_tag; u32 packet_buffer; u32 extradata_buffer; - u32 data[1]; + u32 data; }; struct hfi_session_empty_buffer_uncompressed_plane1_pkt { @@ -177,7 +177,7 @@ struct hfi_session_empty_buffer_uncompressed_plane1_pkt { u32 filled_len; u32 offset; u32 packet_buffer2; - u32 data[1]; + u32 data; }; struct hfi_session_empty_buffer_uncompressed_plane2_pkt { @@ -186,7 +186,7 @@ struct hfi_session_empty_buffer_uncompressed_plane2_pkt { u32 filled_len; u32 offset; u32 packet_buffer3; - u32 data[1]; + u32 data; }; struct hfi_session_fill_buffer_pkt { @@ -198,7 +198,7 @@ struct hfi_session_fill_buffer_pkt { u32 output_tag; u32 packet_buffer; u32 extradata_buffer; - u32 data[1]; + u32 data; }; struct hfi_session_flush_pkt { @@ -217,7 +217,7 @@ struct hfi_session_resume_pkt { struct hfi_session_get_property_pkt { struct hfi_session_hdr_pkt shdr; u32 num_properties; - u32 data[1]; + u32 data; }; struct hfi_session_release_buffer_pkt { @@ -227,7 +227,7 @@ struct hfi_session_release_buffer_pkt { u32 extradata_size; u32 response_req; u32 num_buffers; - u32 buffer_info[1]; + u32 buffer_info[] __counted_by(num_buffers); }; struct hfi_session_release_resources_pkt { diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h b/drivers/media/platform/qcom/venus/hfi_helper.h index e4c05d62cfc7..f44059f19505 100644 --- a/drivers/media/platform/qcom/venus/hfi_helper.h +++ b/drivers/media/platform/qcom/venus/hfi_helper.h @@ -761,7 +761,7 @@ struct hfi_multi_stream_3x { struct hfi_multi_view_format { u32 views; - u32 view_order[1]; + u32 view_order[]; }; #define HFI_MULTI_SLICE_OFF 0x1 @@ -1005,13 +1005,13 @@ struct hfi_uncompressed_plane_constraints { struct hfi_uncompressed_plane_info { u32 format; u32 num_planes; - struct hfi_uncompressed_plane_constraints plane_constraints[1]; + struct hfi_uncompressed_plane_constraints plane_constraints; }; struct hfi_uncompressed_format_supported { u32 buffer_type; u32 format_entries; - struct hfi_uncompressed_plane_info plane_info[1]; + struct hfi_uncompressed_plane_info plane_info; }; struct hfi_uncompressed_plane_actual { @@ -1038,7 +1038,7 @@ struct hfi_codec_supported { struct hfi_properties_supported { u32 num_properties; - u32 properties[1]; + u32 properties[]; }; struct hfi_max_sessions_supported { @@ -1085,12 +1085,12 @@ struct hfi_resource_ocmem_requirement { struct hfi_resource_ocmem_requirement_info { u32 num_entries; - struct hfi_resource_ocmem_requirement requirements[1]; + struct hfi_resource_ocmem_requirement requirements[]; }; struct hfi_property_sys_image_version_info_type { u32 string_size; - u8 str_image_version[1]; + u8 str_image_version[]; }; struct hfi_codec_mask_supported { @@ -1141,7 +1141,7 @@ struct hfi_extradata_header { u32 port_index; u32 type; u32 data_size; - u8 data[1]; + u8 data[]; }; struct hfi_batch_info { @@ -1236,7 +1236,7 @@ static inline void hfi_bufreq_set_count_min_host(struct hfi_buffer_requirements struct hfi_data_payload { u32 size; - u8 data[1]; + u8 data[]; }; struct hfi_enable_picture { @@ -1264,12 +1264,12 @@ struct hfi_interlace_format_supported { struct hfi_buffer_alloc_mode_supported { u32 buffer_type; u32 num_entries; - u32 data[1]; + u32 data[]; }; struct hfi_mb_error_map { u32 error_map_size; - u8 error_map[1]; + u8 error_map[]; }; struct hfi_metadata_pass_through { diff --git a/drivers/media/platform/qcom/venus/hfi_parser.c b/drivers/media/platform/qcom/venus/hfi_parser.c index c43839539d4d..3df241dc3a11 100644 --- a/drivers/media/platform/qcom/venus/hfi_parser.c +++ b/drivers/media/platform/qcom/venus/hfi_parser.c @@ -157,7 +157,7 @@ static void parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data) { struct hfi_uncompressed_format_supported *fmt = data; - struct hfi_uncompressed_plane_info *pinfo = fmt->plane_info; + struct hfi_uncompressed_plane_info *pinfo = &fmt->plane_info; struct hfi_uncompressed_plane_constraints *constr; struct raw_formats rawfmts[MAX_FMT_ENTRIES] = {}; u32 entries = fmt->format_entries; diff --git a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c index f5a655973c08..6289166786ec 100644 --- a/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c +++ b/drivers/media/platform/qcom/venus/hfi_plat_bufs_v6.c @@ -1063,51 +1063,51 @@ struct enc_bufsize_ops { u32 (*persist)(void); }; -static struct dec_bufsize_ops dec_h264_ops = { +static const struct dec_bufsize_ops dec_h264_ops = { .scratch = h264d_scratch_size, .scratch1 = h264d_scratch1_size, .persist1 = h264d_persist1_size, }; -static struct dec_bufsize_ops dec_h265_ops = { +static const struct dec_bufsize_ops dec_h265_ops = { .scratch = h265d_scratch_size, .scratch1 = h265d_scratch1_size, .persist1 = h265d_persist1_size, }; -static struct dec_bufsize_ops dec_vp8_ops = { +static const struct dec_bufsize_ops dec_vp8_ops = { .scratch = vpxd_scratch_size, .scratch1 = vp8d_scratch1_size, .persist1 = vp8d_persist1_size, }; -static struct dec_bufsize_ops dec_vp9_ops = { +static const struct dec_bufsize_ops dec_vp9_ops = { .scratch = vpxd_scratch_size, .scratch1 = vp9d_scratch1_size, .persist1 = vp9d_persist1_size, }; -static struct dec_bufsize_ops dec_mpeg2_ops = { +static const struct dec_bufsize_ops dec_mpeg2_ops = { .scratch = mpeg2d_scratch_size, .scratch1 = mpeg2d_scratch1_size, .persist1 = mpeg2d_persist1_size, }; -static struct enc_bufsize_ops enc_h264_ops = { +static const struct enc_bufsize_ops enc_h264_ops = { .scratch = h264e_scratch_size, .scratch1 = h264e_scratch1_size, .scratch2 = enc_scratch2_size, .persist = enc_persist_size, }; -static struct enc_bufsize_ops enc_h265_ops = { +static const struct enc_bufsize_ops enc_h265_ops = { .scratch = h265e_scratch_size, .scratch1 = h265e_scratch1_size, .scratch2 = enc_scratch2_size, .persist = enc_persist_size, }; -static struct enc_bufsize_ops enc_vp8_ops = { +static const struct enc_bufsize_ops enc_vp8_ops = { .scratch = vp8e_scratch_size, .scratch1 = vp8e_scratch1_size, .scratch2 = enc_scratch2_size, @@ -1186,7 +1186,7 @@ static int bufreq_dec(struct hfi_plat_buffers_params *params, u32 buftype, u32 codec = params->codec; u32 width = params->width, height = params->height, out_min_count; u32 out_width = params->out_width, out_height = params->out_height; - struct dec_bufsize_ops *dec_ops; + const struct dec_bufsize_ops *dec_ops; bool is_secondary_output = params->dec.is_secondary_output; bool is_interlaced = params->dec.is_interlaced; u32 max_mbs_per_frame = params->dec.max_mbs_per_frame; @@ -1260,7 +1260,7 @@ static int bufreq_enc(struct hfi_plat_buffers_params *params, u32 buftype, struct hfi_buffer_requirements *bufreq) { enum hfi_version version = params->version; - struct enc_bufsize_ops *enc_ops; + const struct enc_bufsize_ops *enc_ops; u32 width = params->width; u32 height = params->height; bool is_tenbit = params->enc.is_tenbit; diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c index f9437b6412b9..a9167867063c 100644 --- a/drivers/media/platform/qcom/venus/hfi_venus.c +++ b/drivers/media/platform/qcom/venus/hfi_venus.c @@ -1178,16 +1178,6 @@ static int venus_core_deinit(struct venus_core *core) return 0; } -static int venus_core_ping(struct venus_core *core, u32 cookie) -{ - struct venus_hfi_device *hdev = to_hfi_priv(core); - struct hfi_sys_ping_pkt pkt; - - pkt_sys_ping(&pkt, cookie); - - return venus_iface_cmdq_write(hdev, &pkt, false); -} - static int venus_core_trigger_ssr(struct venus_core *core, u32 trigger_type) { struct venus_hfi_device *hdev = to_hfi_priv(core); @@ -1639,7 +1629,6 @@ static int venus_suspend(struct venus_core *core) static const struct hfi_ops venus_hfi_ops = { .core_init = venus_core_init, .core_deinit = venus_core_deinit, - .core_ping = venus_core_ping, .core_trigger_ssr = venus_core_trigger_ssr, .session_init = venus_session_init, diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c index a1b127caa90a..33a5a659c0ad 100644 --- a/drivers/media/platform/qcom/venus/pm_helpers.c +++ b/drivers/media/platform/qcom/venus/pm_helpers.c @@ -412,10 +412,9 @@ static int vcodec_control_v4(struct venus_core *core, u32 coreid, bool enable) u32 val; int ret; - if (IS_V6(core)) { - ctrl = core->wrapper_base + WRAPPER_CORE_POWER_CONTROL_V6; - stat = core->wrapper_base + WRAPPER_CORE_POWER_STATUS_V6; - } else if (coreid == VIDC_CORE_ID_1) { + if (IS_V6(core)) + return dev_pm_genpd_set_hwmode(core->pmdomains->pd_devs[coreid], !enable); + else if (coreid == VIDC_CORE_ID_1) { ctrl = core->wrapper_base + WRAPPER_VCODEC0_MMCC_POWER_CONTROL; stat = core->wrapper_base + WRAPPER_VCODEC0_MMCC_POWER_STATUS; } else { @@ -451,11 +450,13 @@ static int poweroff_coreid(struct venus_core *core, unsigned int coreid_mask) vcodec_clks_disable(core, core->vcodec0_clks); - ret = vcodec_control_v4(core, VIDC_CORE_ID_1, false); - if (ret) - return ret; + if (!IS_V6(core)) { + ret = vcodec_control_v4(core, VIDC_CORE_ID_1, false); + if (ret) + return ret; + } - ret = pm_runtime_put_sync(core->pmdomains[1]); + ret = pm_runtime_put_sync(core->pmdomains->pd_devs[1]); if (ret < 0) return ret; } @@ -467,11 +468,13 @@ static int poweroff_coreid(struct venus_core *core, unsigned int coreid_mask) vcodec_clks_disable(core, core->vcodec1_clks); - ret = vcodec_control_v4(core, VIDC_CORE_ID_2, false); - if (ret) - return ret; + if (!IS_V6(core)) { + ret = vcodec_control_v4(core, VIDC_CORE_ID_2, false); + if (ret) + return ret; + } - ret = pm_runtime_put_sync(core->pmdomains[2]); + ret = pm_runtime_put_sync(core->pmdomains->pd_devs[2]); if (ret < 0) return ret; } @@ -484,13 +487,15 @@ static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask) int ret; if (coreid_mask & VIDC_CORE_ID_1) { - ret = pm_runtime_get_sync(core->pmdomains[1]); + ret = pm_runtime_get_sync(core->pmdomains->pd_devs[1]); if (ret < 0) return ret; - ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true); - if (ret) - return ret; + if (!IS_V6(core)) { + ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true); + if (ret) + return ret; + } ret = vcodec_clks_enable(core, core->vcodec0_clks); if (ret) @@ -502,13 +507,15 @@ static int poweron_coreid(struct venus_core *core, unsigned int coreid_mask) } if (coreid_mask & VIDC_CORE_ID_2) { - ret = pm_runtime_get_sync(core->pmdomains[2]); + ret = pm_runtime_get_sync(core->pmdomains->pd_devs[2]); if (ret < 0) return ret; - ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true); - if (ret) - return ret; + if (!IS_V6(core)) { + ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true); + if (ret) + return ret; + } ret = vcodec_clks_enable(core, core->vcodec1_clks); if (ret) @@ -857,74 +864,36 @@ static int venc_power_v4(struct device *dev, int on) static int vcodec_domains_get(struct venus_core *core) { int ret; - struct device **opp_virt_dev; struct device *dev = core->dev; const struct venus_resources *res = core->res; - struct device *pd; - unsigned int i; + struct dev_pm_domain_attach_data vcodec_data = { + .pd_names = res->vcodec_pmdomains, + .num_pd_names = res->vcodec_pmdomains_num, + .pd_flags = PD_FLAG_NO_DEV_LINK, + }; + struct dev_pm_domain_attach_data opp_pd_data = { + .pd_names = res->opp_pmdomain, + .num_pd_names = 1, + .pd_flags = PD_FLAG_DEV_LINK_ON | PD_FLAG_REQUIRED_OPP, + }; if (!res->vcodec_pmdomains_num) goto skip_pmdomains; - for (i = 0; i < res->vcodec_pmdomains_num; i++) { - pd = dev_pm_domain_attach_by_name(dev, - res->vcodec_pmdomains[i]); - if (IS_ERR_OR_NULL(pd)) - return pd ? PTR_ERR(pd) : -ENODATA; - core->pmdomains[i] = pd; - } + ret = devm_pm_domain_attach_list(dev, &vcodec_data, &core->pmdomains); + if (ret < 0) + return ret; skip_pmdomains: - if (!core->res->opp_pmdomain) + if (!res->opp_pmdomain) return 0; /* Attach the power domain for setting performance state */ - ret = devm_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev); - if (ret) - goto opp_attach_err; - - core->opp_pmdomain = *opp_virt_dev; - core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain, - DL_FLAG_RPM_ACTIVE | - DL_FLAG_PM_RUNTIME | - DL_FLAG_STATELESS); - if (!core->opp_dl_venus) { - ret = -ENODEV; - goto opp_attach_err; - } + ret = devm_pm_domain_attach_list(dev, &opp_pd_data, &core->opp_pmdomain); + if (ret < 0) + return ret; return 0; - -opp_attach_err: - for (i = 0; i < res->vcodec_pmdomains_num; i++) { - if (IS_ERR_OR_NULL(core->pmdomains[i])) - continue; - dev_pm_domain_detach(core->pmdomains[i], true); - } - - return ret; -} - -static void vcodec_domains_put(struct venus_core *core) -{ - const struct venus_resources *res = core->res; - unsigned int i; - - if (!res->vcodec_pmdomains_num) - goto skip_pmdomains; - - for (i = 0; i < res->vcodec_pmdomains_num; i++) { - if (IS_ERR_OR_NULL(core->pmdomains[i])) - continue; - dev_pm_domain_detach(core->pmdomains[i], true); - } - -skip_pmdomains: - if (!core->has_opp_table) - return; - - if (core->opp_dl_venus) - device_link_del(core->opp_dl_venus); } static int core_resets_reset(struct venus_core *core) @@ -1013,9 +982,7 @@ static int core_get_v4(struct venus_core *core) if (core->res->opp_pmdomain) { ret = devm_pm_opp_of_add_table(dev); - if (!ret) { - core->has_opp_table = true; - } else if (ret != -ENODEV) { + if (ret && ret != -ENODEV) { dev_err(dev, "invalid OPP table in device tree\n"); return ret; } @@ -1026,16 +993,13 @@ static int core_get_v4(struct venus_core *core) static void core_put_v4(struct venus_core *core) { - if (legacy_binding) - return; - - vcodec_domains_put(core); } static int core_power_v4(struct venus_core *core, int on) { struct device *dev = core->dev; - struct device *pmctrl = core->pmdomains[0]; + struct device *pmctrl = core->pmdomains ? + core->pmdomains->pd_devs[0] : NULL; int ret = 0; if (on == POWER_ON) { diff --git a/drivers/media/platform/qcom/venus/vdec.c b/drivers/media/platform/qcom/venus/vdec.c index 29130a9441e7..9f82882b77bc 100644 --- a/drivers/media/platform/qcom/venus/vdec.c +++ b/drivers/media/platform/qcom/venus/vdec.c @@ -1255,7 +1255,7 @@ static int vdec_stop_output(struct venus_inst *inst) break; case VENUS_DEC_STATE_INIT: case VENUS_DEC_STATE_CAPTURE_SETUP: - ret = hfi_session_flush(inst, HFI_FLUSH_INPUT, true); + ret = hfi_session_flush(inst, HFI_FLUSH_ALL, true); break; default: break; @@ -1697,10 +1697,6 @@ static int vdec_open(struct file *file) if (ret) goto err_free; - ret = hfi_session_create(inst, &vdec_hfi_ops); - if (ret) - goto err_ctrl_deinit; - vdec_inst_init(inst); ida_init(&inst->dpb_ids); @@ -1712,15 +1708,19 @@ static int vdec_open(struct file *file) inst->m2m_dev = v4l2_m2m_init(&vdec_m2m_ops); if (IS_ERR(inst->m2m_dev)) { ret = PTR_ERR(inst->m2m_dev); - goto err_session_destroy; + goto err_ctrl_deinit; } inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init); if (IS_ERR(inst->m2m_ctx)) { ret = PTR_ERR(inst->m2m_ctx); - goto err_m2m_release; + goto err_m2m_dev_release; } + ret = hfi_session_create(inst, &vdec_hfi_ops); + if (ret) + goto err_m2m_ctx_release; + v4l2_fh_init(&inst->fh, core->vdev_dec); inst->fh.ctrl_handler = &inst->ctrl_handler; @@ -1730,12 +1730,12 @@ static int vdec_open(struct file *file) return 0; -err_m2m_release: +err_m2m_ctx_release: + v4l2_m2m_ctx_release(inst->m2m_ctx); +err_m2m_dev_release: v4l2_m2m_release(inst->m2m_dev); -err_session_destroy: - hfi_session_destroy(inst); err_ctrl_deinit: - vdec_ctrl_deinit(inst); + v4l2_ctrl_handler_free(&inst->ctrl_handler); err_free: kfree(inst); return ret; @@ -1746,17 +1746,9 @@ static int vdec_close(struct file *file) struct venus_inst *inst = to_inst(file); vdec_pm_get(inst); - - v4l2_m2m_ctx_release(inst->m2m_ctx); - v4l2_m2m_release(inst->m2m_dev); - vdec_ctrl_deinit(inst); + cancel_work_sync(&inst->delayed_process_work); + venus_close_common(inst); ida_destroy(&inst->dpb_ids); - hfi_session_destroy(inst); - mutex_destroy(&inst->lock); - mutex_destroy(&inst->ctx_q_lock); - v4l2_fh_del(&inst->fh); - v4l2_fh_exit(&inst->fh); - vdec_pm_put(inst, false); kfree(inst); @@ -1874,7 +1866,7 @@ MODULE_DEVICE_TABLE(of, vdec_dt_match); static struct platform_driver qcom_venus_dec_driver = { .probe = vdec_probe, - .remove_new = vdec_remove, + .remove = vdec_remove, .driver = { .name = "qcom-venus-decoder", .of_match_table = vdec_dt_match, diff --git a/drivers/media/platform/qcom/venus/vdec.h b/drivers/media/platform/qcom/venus/vdec.h index 6b262d0bf561..0cf981108ff0 100644 --- a/drivers/media/platform/qcom/venus/vdec.h +++ b/drivers/media/platform/qcom/venus/vdec.h @@ -9,6 +9,5 @@ struct venus_inst; int vdec_ctrl_init(struct venus_inst *inst); -void vdec_ctrl_deinit(struct venus_inst *inst); #endif diff --git a/drivers/media/platform/qcom/venus/vdec_ctrls.c b/drivers/media/platform/qcom/venus/vdec_ctrls.c index 7e0f29bf7fae..36ed955b0419 100644 --- a/drivers/media/platform/qcom/venus/vdec_ctrls.c +++ b/drivers/media/platform/qcom/venus/vdec_ctrls.c @@ -187,8 +187,3 @@ int vdec_ctrl_init(struct venus_inst *inst) return 0; } - -void vdec_ctrl_deinit(struct venus_inst *inst) -{ - v4l2_ctrl_handler_free(&inst->ctrl_handler); -} diff --git a/drivers/media/platform/qcom/venus/venc.c b/drivers/media/platform/qcom/venus/venc.c index 3ec2fb8d9fab..c7f8e37dba9b 100644 --- a/drivers/media/platform/qcom/venus/venc.c +++ b/drivers/media/platform/qcom/venus/venc.c @@ -734,6 +734,29 @@ static int venc_set_properties(struct venus_inst *inst) if (ret) return ret; + if (ctr->layer_bitrate) { + unsigned int i; + + ptype = HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER; + ret = hfi_session_set_property(inst, ptype, &ctr->h264_hier_layers); + if (ret) + return ret; + + ptype = HFI_PROPERTY_CONFIG_VENC_HIER_P_ENH_LAYER; + ret = hfi_session_set_property(inst, ptype, &ctr->layer_bitrate); + if (ret) + return ret; + + for (i = 0; i < ctr->h264_hier_layers; ++i) { + ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE; + brate.bitrate = ctr->h264_hier_layer_bitrate[i]; + brate.layer_id = i; + + ret = hfi_session_set_property(inst, ptype, &brate); + if (ret) + return ret; + } + } } if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 || @@ -823,18 +846,33 @@ static int venc_set_properties(struct venus_inst *inst) return ret; } - if (!ctr->bitrate) - bitrate = 64000; - else - bitrate = ctr->bitrate; + if (!ctr->layer_bitrate) { + if (!ctr->bitrate) + bitrate = 64000; + else + bitrate = ctr->bitrate; - ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE; - brate.bitrate = bitrate; - brate.layer_id = 0; + ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE; + brate.bitrate = bitrate; + brate.layer_id = 0; - ret = hfi_session_set_property(inst, ptype, &brate); - if (ret) - return ret; + ret = hfi_session_set_property(inst, ptype, &brate); + if (ret) + return ret; + + if (!ctr->bitrate_peak) + bitrate *= 2; + else + bitrate = ctr->bitrate_peak; + + ptype = HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE; + brate.bitrate = bitrate; + brate.layer_id = 0; + + ret = hfi_session_set_property(inst, ptype, &brate); + if (ret) + return ret; + } if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 || inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) { @@ -849,19 +887,6 @@ static int venc_set_properties(struct venus_inst *inst) return ret; } - if (!ctr->bitrate_peak) - bitrate *= 2; - else - bitrate = ctr->bitrate_peak; - - ptype = HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE; - brate.bitrate = bitrate; - brate.layer_id = 0; - - ret = hfi_session_set_property(inst, ptype, &brate); - if (ret) - return ret; - ptype = HFI_PROPERTY_PARAM_VENC_SESSION_QP; if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) { quant.qp_i = ctr->hevc_i_qp; @@ -1467,10 +1492,6 @@ static int venc_open(struct file *file) if (ret) goto err_free; - ret = hfi_session_create(inst, &venc_hfi_ops); - if (ret) - goto err_ctrl_deinit; - venc_inst_init(inst); /* @@ -1480,15 +1501,19 @@ static int venc_open(struct file *file) inst->m2m_dev = v4l2_m2m_init(&venc_m2m_ops); if (IS_ERR(inst->m2m_dev)) { ret = PTR_ERR(inst->m2m_dev); - goto err_session_destroy; + goto err_ctrl_deinit; } inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init); if (IS_ERR(inst->m2m_ctx)) { ret = PTR_ERR(inst->m2m_ctx); - goto err_m2m_release; + goto err_m2m_dev_release; } + ret = hfi_session_create(inst, &venc_hfi_ops); + if (ret) + goto err_m2m_ctx_release; + v4l2_fh_init(&inst->fh, core->vdev_enc); inst->fh.ctrl_handler = &inst->ctrl_handler; @@ -1498,12 +1523,12 @@ static int venc_open(struct file *file) return 0; -err_m2m_release: +err_m2m_ctx_release: + v4l2_m2m_ctx_release(inst->m2m_ctx); +err_m2m_dev_release: v4l2_m2m_release(inst->m2m_dev); -err_session_destroy: - hfi_session_destroy(inst); err_ctrl_deinit: - venc_ctrl_deinit(inst); + v4l2_ctrl_handler_free(&inst->ctrl_handler); err_free: kfree(inst); return ret; @@ -1514,18 +1539,8 @@ static int venc_close(struct file *file) struct venus_inst *inst = to_inst(file); venc_pm_get(inst); - - v4l2_m2m_ctx_release(inst->m2m_ctx); - v4l2_m2m_release(inst->m2m_dev); - venc_ctrl_deinit(inst); - hfi_session_destroy(inst); - mutex_destroy(&inst->lock); - mutex_destroy(&inst->ctx_q_lock); - v4l2_fh_del(&inst->fh); - v4l2_fh_exit(&inst->fh); - + venus_close_common(inst); inst->enc_state = VENUS_ENC_STATE_DEINIT; - venc_pm_put(inst, false); kfree(inst); @@ -1643,7 +1658,7 @@ MODULE_DEVICE_TABLE(of, venc_dt_match); static struct platform_driver qcom_venus_enc_driver = { .probe = venc_probe, - .remove_new = venc_remove, + .remove = venc_remove, .driver = { .name = "qcom-venus-encoder", .of_match_table = venc_dt_match, diff --git a/drivers/media/platform/qcom/venus/venc.h b/drivers/media/platform/qcom/venus/venc.h index 4ea37fdcd9b8..719d0f73b14b 100644 --- a/drivers/media/platform/qcom/venus/venc.h +++ b/drivers/media/platform/qcom/venus/venc.h @@ -9,6 +9,5 @@ struct venus_inst; int venc_ctrl_init(struct venus_inst *inst); -void venc_ctrl_deinit(struct venus_inst *inst); #endif diff --git a/drivers/media/platform/qcom/venus/venc_ctrls.c b/drivers/media/platform/qcom/venus/venc_ctrls.c index d9d2a293f3ef..51801a962ed2 100644 --- a/drivers/media/platform/qcom/venus/venc_ctrls.c +++ b/drivers/media/platform/qcom/venus/venc_ctrls.c @@ -67,12 +67,28 @@ static int venc_calc_bpframes(u32 gop_size, u32 conseq_b, u32 *bf, u32 *pf) return 0; } +static int dynamic_bitrate_update(struct venus_inst *inst, u32 bitrate, + u32 layer_id) +{ + int ret = 0; + + mutex_lock(&inst->lock); + if (inst->streamon_out && inst->streamon_cap) { + u32 ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE; + struct hfi_bitrate brate = { .bitrate = bitrate, .layer_id = layer_id }; + + ret = hfi_session_set_property(inst, ptype, &brate); + } + mutex_unlock(&inst->lock); + + return ret; +} + static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) { struct venus_inst *inst = ctrl_to_inst(ctrl); struct venc_controls *ctr = &inst->controls.enc; struct hfi_enable en = { .enable = 1 }; - struct hfi_bitrate brate; struct hfi_ltr_use ltr_use; struct hfi_ltr_mark ltr_mark; u32 bframes; @@ -85,19 +101,9 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) break; case V4L2_CID_MPEG_VIDEO_BITRATE: ctr->bitrate = ctrl->val; - mutex_lock(&inst->lock); - if (inst->streamon_out && inst->streamon_cap) { - ptype = HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE; - brate.bitrate = ctr->bitrate; - brate.layer_id = 0; - - ret = hfi_session_set_property(inst, ptype, &brate); - if (ret) { - mutex_unlock(&inst->lock); - return ret; - } - } - mutex_unlock(&inst->lock); + ret = dynamic_bitrate_update(inst, ctr->bitrate, 0); + if (ret) + return ret; break; case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: ctr->bitrate_peak = ctrl->val; @@ -340,6 +346,55 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl) ctr->h264_8x8_transform = ctrl->val; break; + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE: + if (ctrl->val != V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P) + return -EINVAL; + break; + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING: + ctr->layer_bitrate = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER: + if (ctrl->val > VIDC_MAX_HIER_CODING_LAYER) + return -EINVAL; + ctr->h264_hier_layers = ctrl->val; + break; + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L0_BR: + ctr->h264_hier_layer_bitrate[0] = ctrl->val; + ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[0], 0); + if (ret) + return ret; + break; + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L1_BR: + ctr->h264_hier_layer_bitrate[1] = ctrl->val; + ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[1], 1); + if (ret) + return ret; + break; + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L2_BR: + ctr->h264_hier_layer_bitrate[2] = ctrl->val; + ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[2], 2); + if (ret) + return ret; + break; + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L3_BR: + ctr->h264_hier_layer_bitrate[3] = ctrl->val; + ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[3], 3); + if (ret) + return ret; + break; + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L4_BR: + ctr->h264_hier_layer_bitrate[4] = ctrl->val; + ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[4], 4); + if (ret) + return ret; + break; + case V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L5_BR: + ctr->h264_hier_layer_bitrate[5] = ctrl->val; + ret = dynamic_bitrate_update(inst, ctr->h264_hier_layer_bitrate[5], 5); + if (ret) + return ret; + break; + default: return -EINVAL; } @@ -622,6 +677,49 @@ int venc_ctrl_init(struct venus_inst *inst) V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD, 0, ((4096 * 2304) >> 8), 1, 0); + if (IS_V4(inst->core) || IS_V6(inst->core)) { + v4l2_ctrl_new_std_menu(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE, + V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P, + 1, V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING, 0, 1, 1, 0); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER, 0, + VIDC_MAX_HIER_CODING_LAYER, 1, 0); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L0_BR, + BITRATE_MIN, BITRATE_MAX, BITRATE_STEP, BITRATE_DEFAULT); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L1_BR, + BITRATE_MIN, BITRATE_MAX, + BITRATE_STEP, BITRATE_DEFAULT); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L2_BR, + BITRATE_MIN, BITRATE_MAX, + BITRATE_STEP, BITRATE_DEFAULT); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L3_BR, + BITRATE_MIN, BITRATE_MAX, + BITRATE_STEP, BITRATE_DEFAULT); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L4_BR, + BITRATE_MIN, BITRATE_MAX, + BITRATE_STEP, BITRATE_DEFAULT); + + v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops, + V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L5_BR, + BITRATE_MIN, BITRATE_MAX, + BITRATE_STEP, BITRATE_DEFAULT); + } + ret = inst->ctrl_handler.error; if (ret) goto err; @@ -635,8 +733,3 @@ err: v4l2_ctrl_handler_free(&inst->ctrl_handler); return ret; } - -void venc_ctrl_deinit(struct venus_inst *inst) -{ - v4l2_ctrl_handler_free(&inst->ctrl_handler); -} |