From a285b5127c9de7797d11929cc3aac32862ada988 Mon Sep 17 00:00:00 2001 From: zouxiaoh Date: Wed, 7 Dec 2022 16:19:40 +0800 Subject: [PATCH] RPL-P Beta release (#70) Signed-off-by: zouxiaoh Signed-off-by: zouxiaoh --- Makefile | 2 + README.md | 2 +- drivers/media/i2c/imx390.c | 39 +- drivers/media/i2c/ti960-des.c | 472 ++++++++++-------- drivers/media/i2c/ti960-reg.h | 6 +- drivers/media/i2c/ti964.c | 54 +- drivers/media/pci/intel/Kconfig | 4 +- drivers/media/pci/intel/ipu-bus.c | 39 +- drivers/media/pci/intel/ipu-bus.h | 12 +- drivers/media/pci/intel/ipu-isys-queue.c | 2 +- drivers/media/pci/intel/ipu-isys.c | 13 +- drivers/media/pci/intel/ipu-psys.c | 20 +- drivers/media/pci/intel/ipu.c | 53 +- drivers/media/pci/intel/ipu6/Makefile | 4 +- drivers/media/platform/intel/Kconfig | 4 +- .../media/platform/intel/ipu6-adlrvp-pdata.c | 113 +++-- .../media/platform/intel/ipu6-tglrvp-pdata.c | 10 + 17 files changed, 532 insertions(+), 317 deletions(-) diff --git a/Makefile b/Makefile index 29e1df2051a7..85db49c66a69 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,8 @@ export EXTERNAL_BUILD = 1 export CONFIG_VIDEO_INTEL_IPU6 = m +export CONFIG_VIDEO_INTEL_IPU_SOC = y +export CONFIG_VIDEO_INTEL_IPU_USE_PLATFORMDATA = y export CONFIG_INTEL_SKL_INT3472 = m export CONFIG_INTEL_IPU6_ACPI = m obj-y += drivers/media/pci/intel/ diff --git a/README.md b/README.md index 5a9704cc1286..26d1e0afef74 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ obj-$(CONFIG_VIDEO_D4XX) += d4xx.o CONFIG_VIDEO_D4XX=m CONFIG_INTEL_IPU6_ACPI=m CONFIG_VIDEO_INTEL_IPU_SOC=y - CONFIG_VIDEO_INTEL_IPU_USE_PLATFORMDATA=m + CONFIG_VIDEO_INTEL_IPU_USE_PLATFORMDATA=y ``` ### 2. Build outside kernel source tree diff --git a/drivers/media/i2c/imx390.c b/drivers/media/i2c/imx390.c index 654793cf76a5..5fe696a2e8e8 100644 --- a/drivers/media/i2c/imx390.c +++ b/drivers/media/i2c/imx390.c @@ -1685,7 +1685,11 @@ static int __maybe_unused imx390_resume(struct device *dev) } static int imx390_set_format(struct v4l2_subdev *sd, +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif struct v4l2_subdev_format *fmt) { struct imx390 *imx390 = to_imx390(sd); @@ -1714,7 +1718,11 @@ static int imx390_set_format(struct v4l2_subdev *sd, imx390_update_pad_format(mode, &fmt->format); if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; +#else + *v4l2_subdev_get_try_format(sd, sd_state, fmt->pad) = fmt->format; +#endif } else { imx390->cur_mode = mode; __v4l2_ctrl_s_ctrl(imx390->link_freq, mode->link_freq_index); @@ -1746,15 +1754,24 @@ static int imx390_set_format(struct v4l2_subdev *sd, } static int imx390_get_format(struct v4l2_subdev *sd, +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif struct v4l2_subdev_format *fmt) { struct imx390 *imx390 = to_imx390(sd); mutex_lock(&imx390->mutex); if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) fmt->format = *v4l2_subdev_get_try_format(&imx390->sd, cfg, fmt->pad); +#else + fmt->format = *v4l2_subdev_get_try_format(&imx390->sd, sd_state, + fmt->pad); +#endif else imx390_update_pad_format(imx390->cur_mode, &fmt->format); @@ -1774,14 +1791,17 @@ static int imx390_get_frame_desc(struct v4l2_subdev *sd, desc->entry[i].flags = 0; desc->entry[i].pixelcode = MEDIA_BUS_FMT_FIXED; desc->entry[i].length = 0; - desc->entry[i].bus.csi2.channel = i; } return 0; } static int imx390_enum_mbus_code(struct v4l2_subdev *sd, +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif struct v4l2_subdev_mbus_code_enum *code) { if (code->index >= ARRAY_SIZE(supported_formats)) @@ -1793,7 +1813,11 @@ static int imx390_enum_mbus_code(struct v4l2_subdev *sd, } static int imx390_enum_frame_size(struct v4l2_subdev *sd, +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif struct v4l2_subdev_frame_size_enum *fse) { if (fse->index >= ARRAY_SIZE(supported_modes)) @@ -1810,7 +1834,11 @@ static int imx390_enum_frame_size(struct v4l2_subdev *sd, static int imx390_frame_rate[] = { 40, 20 }; static int imx390_enum_frame_interval(struct v4l2_subdev *subdev, +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif struct v4l2_subdev_frame_interval_enum *fie) { int mode_size = ARRAY_SIZE(supported_modes); @@ -1839,8 +1867,13 @@ static int imx390_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) struct imx390 *imx390 = to_imx390(sd); mutex_lock(&imx390->mutex); +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) imx390_update_pad_format(&supported_modes[0], v4l2_subdev_get_try_format(sd, fh->pad, 0)); +#else + imx390_update_pad_format(&supported_modes[0], + v4l2_subdev_get_try_format(sd, fh->state, 0)); +#endif mutex_unlock(&imx390->mutex); return 0; @@ -1994,7 +2027,11 @@ static int imx390_probe(struct i2c_client *client) goto probe_error_v4l2_ctrl_handler_free; } +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 13, 0) ret = v4l2_async_register_subdev_sensor_common(&imx390->sd); +#else + ret = v4l2_async_register_subdev_sensor(&imx390->sd); +#endif if (ret < 0) { dev_err(&client->dev, "failed to register V4L2 subdev: %d", ret); diff --git a/drivers/media/i2c/ti960-des.c b/drivers/media/i2c/ti960-des.c index 03b055eee7c5..df25ce6121f6 100644 --- a/drivers/media/i2c/ti960-des.c +++ b/drivers/media/i2c/ti960-des.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2022 Intel Corporation #include #include @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -19,6 +20,9 @@ #include "ti960-reg.h" #include "ti953.h" +#define MIPI_CSI2_TYPE_RAW12 0x2c +#define MIPI_CSI2_TYPE_YUV422_8 0x1e + struct ti960_subdev { struct v4l2_subdev *sd; unsigned short rx_port; @@ -47,8 +51,6 @@ struct ti960 { struct rect *crop; struct rect *compose; - struct v4l2_subdev_route *ti960_route; - unsigned int nsinks; unsigned int nsources; unsigned int nstreams; @@ -62,9 +64,15 @@ struct ti960 { #define to_ti960(_sd) container_of(_sd, struct ti960, sd) -static const s64 ti960_op_sys_clock[] = {400000000, 800000000}; +static const s64 ti960_op_sys_clock[] = {200000000, + 400000000, + 600000000, + 800000000}; + static const u8 ti960_op_sys_clock_reg_val[] = { + TI960_MIPI_400MBPS, TI960_MIPI_800MBPS, + TI960_MIPI_1200MBPS, TI960_MIPI_1600MBPS }; @@ -126,6 +134,52 @@ static struct regmap_config ti960_reg_config16 = { .reg_format_endian = REGMAP_ENDIAN_BIG, }; +static s64 ti960_query_sub_stream[NR_OF_TI960_SINK_PADS] = { + 0, 0, 0, 0 +}; + +static void set_sub_stream_fmt(int index, u32 code) +{ + ti960_query_sub_stream[index] &= 0xFFFFFFFFFFFF0000; + ti960_query_sub_stream[index] |= code; +} + +static void set_sub_stream_h(int index, u32 height) +{ + s64 val = height & 0xFFFF; + + ti960_query_sub_stream[index] &= 0xFFFFFFFF0000FFFF; + ti960_query_sub_stream[index] |= val << 16; +} + +static void set_sub_stream_w(int index, u32 width) +{ + s64 val = width & 0xFFFF; + + ti960_query_sub_stream[index] &= 0xFFFF0000FFFFFFFF; + ti960_query_sub_stream[index] |= val << 32; +} + +static void set_sub_stream_dt(int index, u32 dt) +{ + s64 val = dt & 0xFF; + + ti960_query_sub_stream[index] &= 0xFF00FFFFFFFFFFFF; + ti960_query_sub_stream[index] |= val << 48; +} + +static void set_sub_stream_vc_id(int index, u32 vc_id) +{ + s64 val = vc_id & 0xFF; + + ti960_query_sub_stream[index] &= 0x00FFFFFFFFFFFFFF; + ti960_query_sub_stream[index] |= val << 56; +} + +static u8 ti960_set_sub_stream[] = { + 0, 0, 0, 0 +}; + int bus_switch(struct ti960 *va) { int ret; @@ -181,6 +235,7 @@ static int ti960_reg_write(struct ti960 *va, unsigned char reg, unsigned int val int ret, retry, timeout = 10; for (retry = 0; retry < timeout; retry++) { + dev_dbg(va->sd.dev, "write reg %x = %x", reg, val); ret = regmap_write(va->regmap8, reg, val); if (ret < 0) { dev_err(va->sd.dev, "960 reg write ret=%x", ret); @@ -336,86 +391,13 @@ static int ti960_fsin_gpio_init(struct ti960 *va, unsigned short rx_port, return rval; } -static int ti960_get_routing(struct v4l2_subdev *sd, - struct v4l2_subdev_routing *route) -{ - struct ti960 *va = to_ti960(sd); - int i, j; - - /* active routing first */ - j = 0; - for (i = 0; i < va->nstreams; ++i) { - if (j >= route->num_routes) - break; - if (!(va->ti960_route[i].flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) - continue; - route->routes[j].sink_pad = va->ti960_route[i].sink_pad; - route->routes[j].sink_stream = va->ti960_route[i].sink_stream; - route->routes[j].source_pad = va->ti960_route[i].source_pad; - route->routes[j].source_stream = va->ti960_route[i].source_stream; - route->routes[j].flags = va->ti960_route[i].flags; - j++; - } - - for (i = 0; i < va->nstreams; ++i) { - if (j >= route->num_routes) - break; - if (va->ti960_route[i].flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE) - continue; - route->routes[j].sink_pad = va->ti960_route[i].sink_pad; - route->routes[j].sink_stream = va->ti960_route[i].sink_stream; - route->routes[j].source_pad = va->ti960_route[i].source_pad; - route->routes[j].source_stream = va->ti960_route[i].source_stream; - route->routes[j].flags = va->ti960_route[i].flags; - j++; - } - - route->num_routes = i; - - return 0; -} - -static int ti960_set_routing(struct v4l2_subdev *sd, - struct v4l2_subdev_routing *route) -{ - struct ti960 *va = to_ti960(sd); - int i, j, ret = 0; - - for (i = 0; i < min(route->num_routes, va->nstreams); ++i) { - struct v4l2_subdev_route *t = &route->routes[i]; - - if (t->sink_stream > va->nstreams - 1 || - t->source_stream > va->nstreams - 1) - continue; - - if (t->source_pad != TI960_PAD_SOURCE) - continue; - - for (j = 0; j < va->nstreams; j++) { - if (t->sink_pad == va->ti960_route[j].sink_pad && - t->source_pad == va->ti960_route[j].source_pad && - t->sink_stream == va->ti960_route[j].sink_stream && - t->source_stream == va->ti960_route[j].source_stream) - break; - } - - if (j == va->nstreams) - continue; - - if (t->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE) - va->ti960_route[j].flags |= - V4L2_SUBDEV_ROUTE_FL_ACTIVE; - else if (!(t->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) - va->ti960_route[j].flags &= - (~V4L2_SUBDEV_ROUTE_FL_ACTIVE); - } - - return ret; -} - static int ti960_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif + struct v4l2_subdev_mbus_code_enum *code) { struct ti960 *va = to_ti960(sd); const uint32_t *supported_code = @@ -423,25 +405,6 @@ static int ti960_enum_mbus_code(struct v4l2_subdev *sd, bool next_stream = false; int i; - if (code->stream & V4L2_SUBDEV_FLAG_NEXT_STREAM) { - next_stream = true; - code->stream &= ~V4L2_SUBDEV_FLAG_NEXT_STREAM; - } - - if (code->stream > va->nstreams) - return -EINVAL; - - if (next_stream) { - if (!(va->pad[code->pad].flags & MEDIA_PAD_FL_MULTIPLEX)) - return -EINVAL; - if (code->stream < va->nstreams - 1) { - code->stream++; - return 0; - } else { - return -EINVAL; - } - } - for (i = 0; supported_code[i]; i++) { if (i == code->index) { code->code = supported_code[i]; @@ -465,29 +428,12 @@ static const struct ti960_csi_data_format return &va_csi_data_formats[0]; } -static int ti960_get_routing_remote_pad(struct v4l2_subdev *sd, - unsigned int pad) -{ - struct ti960 *va = to_ti960(sd); - int i; - - for (i = 0; i < va->nstreams; ++i) { - if (va->ti960_route[i].sink_pad == pad) - return va->ti960_route[i].source_pad; - if (va->ti960_route[i].source_pad == pad) - return va->ti960_route[i].sink_pad; - } - return -1; -} - static int ti960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad, struct v4l2_mbus_frame_desc *desc) { struct ti960 *va = to_ti960(sd); int sink_pad = pad; - if (va->pad[pad].flags & MEDIA_PAD_FL_SOURCE) - sink_pad = ti960_get_routing_remote_pad(sd, pad); if (sink_pad >= 0) { struct media_pad *remote_pad = media_entity_remote_pad(&sd->entity.pads[sink_pad]); @@ -505,36 +451,60 @@ static int ti960_get_frame_desc(struct v4l2_subdev *sd, static struct v4l2_mbus_framefmt * __ti960_get_ffmt(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - unsigned int pad, unsigned int which, - unsigned int stream) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif + unsigned int pad, unsigned int which, + unsigned int stream) { struct ti960 *va = to_ti960(subdev); + if (pad < 0 || pad >= NR_OF_TI960_PADS || + stream < 0 || stream >= va->nstreams) { + dev_err(subdev->dev, "%s invalid pad %d, or stream %d\n", __func__, pad, stream); + return NULL; + } + if (which == V4L2_SUBDEV_FORMAT_TRY) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) return v4l2_subdev_get_try_format(subdev, cfg, pad); +#else + return v4l2_subdev_get_try_format(subdev, sd_state, pad); +#endif else return &va->ffmts[pad][stream]; } static int ti960_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif + struct v4l2_subdev_format *fmt) { struct ti960 *va = to_ti960(subdev); - - if (fmt->stream > va->nstreams) - return -EINVAL; + struct v4l2_mbus_framefmt *ffmt; mutex_lock(&va->mutex); - fmt->format = *__ti960_get_ffmt(subdev, cfg, fmt->pad, - fmt->which, fmt->stream); +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + ffmt = __ti960_get_ffmt(subdev, cfg, fmt->pad, fmt->which, 0); +#else + ffmt = __ti960_get_ffmt(subdev, sd_state, fmt->pad, fmt->which, 0); +#endif + if (!ffmt) { + mutex_unlock(&va->mutex); + return -EINVAL; + } + fmt->format = *ffmt; mutex_unlock(&va->mutex); - dev_dbg(subdev->dev, "subdev_format: which: %s, pad: %d, stream: %d.\n", + dev_dbg(subdev->dev, "subdev_format: which: %s, pad: %d.\n", fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE ? "V4L2_SUBDEV_FORMAT_ACTIVE" : "V4L2_SUBDEV_FORMAT_TRY", - fmt->pad, fmt->stream); + fmt->pad); dev_dbg(subdev->dev, "framefmt: width: %d, height: %d, code: 0x%x.\n", fmt->format.width, fmt->format.height, fmt->format.code); @@ -543,42 +513,69 @@ static int ti960_get_format(struct v4l2_subdev *subdev, } static int ti960_set_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif + struct v4l2_subdev_format *fmt) { struct ti960 *va = to_ti960(subdev); const struct ti960_csi_data_format *csi_format; struct v4l2_mbus_framefmt *ffmt; - if (fmt->stream > va->nstreams) - return -EINVAL; - csi_format = ti960_validate_csi_data_format( fmt->format.code); mutex_lock(&va->mutex); - ffmt = __ti960_get_ffmt(subdev, cfg, fmt->pad, fmt->which, - fmt->stream); +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + ffmt = __ti960_get_ffmt(subdev, cfg, fmt->pad, fmt->which, 0); +#else + ffmt = __ti960_get_ffmt(subdev, sd_state, fmt->pad, fmt->which, 0); +#endif + if (!ffmt) { + mutex_unlock(&va->mutex); + return -EINVAL; + } if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { ffmt->width = fmt->format.width; ffmt->height = fmt->format.height; ffmt->code = csi_format->code; } fmt->format = *ffmt; - mutex_unlock(&va->mutex); - dev_dbg(subdev->dev, "framefmt: width: %d, height: %d, code: 0x%x.\n", - ffmt->width, ffmt->height, ffmt->code); + if (fmt->pad < NR_OF_TI960_SINK_PADS) { + set_sub_stream_fmt(fmt->pad, ffmt->code); + set_sub_stream_h(fmt->pad, ffmt->height); + set_sub_stream_w(fmt->pad, ffmt->width); + + /* select correct csi-2 data type id */ + if (ffmt->code >= MEDIA_BUS_FMT_UYVY8_1X16 && + ffmt->code <= MEDIA_BUS_FMT_YVYU8_1X16) + set_sub_stream_dt(fmt->pad, MIPI_CSI2_TYPE_YUV422_8); + else + set_sub_stream_dt(fmt->pad, MIPI_CSI2_TYPE_RAW12); + set_sub_stream_vc_id(fmt->pad, fmt->pad); + dev_dbg(subdev->dev, + "framefmt: width: %d, height: %d, code: 0x%x.\n", + ffmt->width, ffmt->height, ffmt->code); + } + mutex_unlock(&va->mutex); return 0; } static int ti960_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_get_try_format(subdev, fh->pad, 0); +#else + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(subdev, fh->state, 0); +#endif struct v4l2_subdev_format fmt = { .which = V4L2_SUBDEV_FORMAT_TRY, @@ -588,7 +585,6 @@ static int ti960_open(struct v4l2_subdev *subdev, .height = TI960_MAX_HEIGHT, .code = MEDIA_BUS_FMT_SBGGR12_1X12, }, - .stream = 0, }; *try_fmt = fmt.format; @@ -796,7 +792,7 @@ static int ti960_registered(struct v4l2_subdev *subdev) rval = media_create_pad_link( #endif &va->sub_devs[k].sd->entity, j, - &va->sd.entity, l, 0); + &va->sd.entity, l, MEDIA_LNK_FL_DYNAMIC); if (rval) { dev_err(va->sd.dev, "can't create link to %c\n", @@ -834,7 +830,7 @@ static int ti960_set_power(struct v4l2_subdev *subdev, int on) val = TI960_CSI_ENABLE; val |= TI960_CSI_CONTS_CLOCK; /* Enable skew calculation when 1.6Gbps output is enabled. */ - if (v4l2_ctrl_g_ctrl(va->link_freq)) + if (v4l2_ctrl_g_ctrl(va->link_freq) == 3) val |= TI960_CSI_SKEWCAL; return ti960_reg_write(va, TI960_CSI_CTL, val); } @@ -857,10 +853,12 @@ static bool ti960_broadcast_mode(struct v4l2_subdev *subdev) if (!remote_pad) continue; + if (!ti960_set_sub_stream[i]) + continue; + sd = media_entity_to_v4l2_subdev(remote_pad->entity); fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE; fmt.pad = remote_pad->index; - fmt.stream = 0; rval = v4l2_subdev_call(sd, pad, get_fmt, NULL, &fmt); if (rval) @@ -914,24 +912,11 @@ static int ti960_rx_port_config(struct ti960 *va, int sink, int rx_port) /* * CSI VC MAPPING. */ - rval = regmap_read(va->regmap8, TI960_CSI_VC_MAP, &csi_vc_map); - if (rval < 0) { - dev_err(va->sd.dev, "960 reg read ret=%x", rval); - return rval; - } - for (i = 0; i < va->nstreams; ++i) { - if (!(va->ti960_route[i].flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE)) - continue; - if (rx_port != va->ti960_route[i].sink_pad) - continue; - csi_vc_map &= ~(0x3 << (va->ti960_route[i].sink_stream & 0x3) * 2); - csi_vc_map |= (va->ti960_route[i].source_stream & 0x3) - << (va->ti960_route[i].sink_stream & 0x3) * 2; - } - dev_dbg(va->sd.dev, "%s port %d, csi_vc_map %x", - __func__, rx_port, csi_vc_map); + csi_vc_map = sink * 0x55; + dev_info(va->sd.dev, "%s sink pad %d, rx_port %d, csi_vc_map %x", + __func__, sink, rx_port, csi_vc_map); rval = ti960_reg_write(va, TI960_CSI_VC_MAP, - csi_vc_map); + csi_vc_map); if (rval) { dev_err(va->sd.dev, "Failed to set port config.\n"); return rval; @@ -953,6 +938,19 @@ static int ti960_find_subdev_index(struct ti960 *va, struct v4l2_subdev *sd) return -EINVAL; } +static int ti960_find_subdev_index_by_rx_port(struct ti960 *va, u8 rx_port) +{ + int i; + + for (i = 0; i < NR_OF_TI960_SINK_PADS; i++) { + if (va->sub_devs[i].rx_port == rx_port) + return i; + } + WARN_ON(1); + + return -EINVAL; +} + static int ti960_set_frame_sync(struct ti960 *va, int enable) { int i, rval; @@ -998,6 +996,9 @@ static int ti960_set_stream(struct v4l2_subdev *subdev, int enable) if (!remote_pad) continue; + if (!ti960_set_sub_stream[i]) + continue; + /* Find ti960 subdev */ sd = media_entity_to_v4l2_subdev(remote_pad->entity); j = ti960_find_subdev_index(va, sd); @@ -1120,35 +1121,57 @@ static int ti960_set_stream(struct v4l2_subdev *subdev, int enable) return 0; } -static struct v4l2_subdev_internal_ops ti960_sd_internal_ops = { - .open = ti960_open, - .registered = ti960_registered, -}; - -static bool ti960_sd_has_route(struct media_entity *entity, - unsigned int pad0, unsigned int pad1, int *stream) +static int ti960_set_stream_vc(struct ti960 *va, u8 vc_id, u8 state) { - struct ti960 *va = to_ti960(media_entity_to_v4l2_subdev(entity)); + unsigned short rx_port; + unsigned short ser_alias; + struct v4l2_subdev *sd; + int rval; int i; - if (va == NULL || stream == NULL || - *stream >= va->nstreams || *stream < 0) - return false; + i = ti960_find_subdev_index_by_rx_port(va, vc_id); + if (i < 0) + return -EINVAL; + rx_port = va->sub_devs[i].rx_port; + ser_alias = va->sub_devs[i].ser_i2c_addr; + sd = va->sub_devs[i].sd; + + rval = ti960_rx_port_config(va, vc_id, rx_port); + if (rval < 0) + return rval; + + rval = v4l2_subdev_call(sd, video, s_stream, state); + if (rval) { + dev_err(va->sd.dev, + "Failed to set stream for %s, enable %d\n", + sd->name, state); + return rval; + } + dev_info(va->sd.dev, "set stream for %s, enable %d\n", + sd->name, state); - for (i = 0; i < va->nstreams; ++i) { - if ((va->ti960_route[*stream].flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE) && - ((va->ti960_route[*stream].source_pad == pad0 && - va->ti960_route[*stream].sink_pad == pad1) || - (va->ti960_route[*stream].source_pad == pad1 && - va->ti960_route[*stream].sink_pad == pad0))) - return true; + /* RX port fordward */ + rval = ti960_reg_set_bit(va, TI960_FWD_CTL1, + rx_port + 4, !state); + if (rval) { + dev_err(va->sd.dev, + "Failed to forward RX port%d. enable %d\n", + i, state); + return rval; + } + if (va->subdev_pdata[i].module_flags & TI960_FL_RESET) { + rval = reset_sensor(va, rx_port, ser_alias, + va->subdev_pdata[i].reset); + if (rval) + return rval; } - return false; + return 0; } -static const struct media_entity_operations ti960_sd_entity_ops = { - .has_route = ti960_sd_has_route, +static struct v4l2_subdev_internal_ops ti960_sd_internal_ops = { + .open = ti960_open, + .registered = ti960_registered, }; static const struct v4l2_subdev_video_ops ti960_sd_video_ops = { @@ -1169,6 +1192,30 @@ static const struct v4l2_subdev_core_ops ti960_core_subdev_ops = { static int ti960_s_ctrl(struct v4l2_ctrl *ctrl) { + struct ti960 *va = container_of(ctrl->handler, + struct ti960, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&va->sd); + u32 val; + u8 vc_id; + u8 state; + + switch (ctrl->id) { + case V4L2_CID_IPU_SET_SUB_STREAM: + val = (*ctrl->p_new.p_s64 & 0xFFFF); + dev_info(va->sd.dev, "V4L2_CID_IPU_SET_SUB_STREAM %x\n", val); + vc_id = (val >> 8) & 0x00FF; + state = val & 0x00FF; + if (vc_id > NR_OF_TI960_SINK_PADS - 1) + dev_err(va->sd.dev, "invalid vc %d\n", vc_id); + else + ti960_set_sub_stream[vc_id] = state; + + ti960_set_stream_vc(va, vc_id, state); + break; + default: + dev_info(va->sd.dev, "unknown control id: 0x%X\n", ctrl->id); + } + return 0; } @@ -1182,10 +1229,10 @@ static const struct v4l2_ctrl_config ti960_controls[] = { .id = V4L2_CID_LINK_FREQ, .name = "V4L2_CID_LINK_FREQ", .type = V4L2_CTRL_TYPE_INTEGER_MENU, + .min = 0, .max = ARRAY_SIZE(ti960_op_sys_clock) - 1, - .min = 0, - .step = 0, - .def = 1, + .def = 3, + .menu_skip_mask = 0, .qmenu_int = ti960_op_sys_clock, }, { @@ -1193,10 +1240,31 @@ static const struct v4l2_ctrl_config ti960_controls[] = { .id = V4L2_CID_TEST_PATTERN, .name = "V4L2_CID_TEST_PATTERN", .type = V4L2_CTRL_TYPE_INTEGER, + .min = 0, .max = 1, - .min = 0, - .step = 1, + .step = 1, + .def = 0, + }, + { + .ops = &ti960_ctrl_ops, + .id = V4L2_CID_IPU_QUERY_SUB_STREAM, + .name = "query virtual channel", + .type = V4L2_CTRL_TYPE_INTEGER_MENU, + .max = ARRAY_SIZE(ti960_query_sub_stream) - 1, + .min = 0, + .def = 0, + .menu_skip_mask = 0, + .qmenu_int = ti960_query_sub_stream, + }, + { + .ops = &ti960_ctrl_ops, + .id = V4L2_CID_IPU_SET_SUB_STREAM, + .name = "set virtual channel", + .type = V4L2_CTRL_TYPE_INTEGER64, + .max = 0xFFFF, + .min = 0, .def = 0, + .step = 1, }, }; @@ -1205,8 +1273,6 @@ static const struct v4l2_subdev_pad_ops ti960_sd_pad_ops = { .set_fmt = ti960_set_format, .get_frame_desc = ti960_get_frame_desc, .enum_mbus_code = ti960_enum_mbus_code, - .set_routing = ti960_set_routing, - .get_routing = ti960_get_routing, }; static struct v4l2_subdev_ops ti960_sd_ops = { @@ -1224,11 +1290,9 @@ static int ti960_register_subdev(struct ti960 *va) snprintf(va->sd.name, sizeof(va->sd.name), "TI960 %c", va->pdata->suffix); - va->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | - V4L2_SUBDEV_FL_HAS_SUBSTREAMS; + va->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; va->sd.internal_ops = &ti960_sd_internal_ops; - va->sd.entity.ops = &ti960_sd_entity_ops; v4l2_set_subdevdata(&va->sd, client); @@ -1264,8 +1328,7 @@ static int ti960_register_subdev(struct ti960 *va) for (i = 0; i < va->nsinks; i++) va->pad[i].flags = MEDIA_PAD_FL_SINK; - va->pad[TI960_PAD_SOURCE].flags = - MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MULTIPLEX; + va->pad[TI960_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0) rval = media_entity_init(&va->sd.entity, NR_OF_TI960_PADS, va->pad, 0); #else @@ -1433,25 +1496,6 @@ static int ti960_probe(struct i2c_client *client, return -ENOMEM; } - va->ti960_route = devm_kcalloc(&client->dev, NR_OF_TI960_STREAMS, - sizeof(struct v4l2_subdev_routing), GFP_KERNEL); - - if (!va->ti960_route) - return -ENOMEM; - - /* routing for virtual channel supports */ - l = 0; - for (i = 0; i < NR_OF_TI960_SINK_PADS; i++) - for (j = 0; j < NR_OF_TI960_VCS_PER_SINK_PAD; j++) - for (k = 0; k < NR_OF_TI960_VCS_SOURCE_PAD; k++) { - va->ti960_route[l].sink_pad = i; - va->ti960_route[l].sink_stream = j; - va->ti960_route[l].source_pad = TI960_PAD_SOURCE; - va->ti960_route[l].source_stream = k; - va->ti960_route[l].flags = MEDIA_PAD_FL_MULTIPLEX; - l++; - } - va->regmap8 = devm_regmap_init_i2c(client, &ti960_reg_config8); if (IS_ERR(va->regmap8)) { diff --git a/drivers/media/i2c/ti960-reg.h b/drivers/media/i2c/ti960-reg.h index fbb63150ec57..6e410c67c7d9 100644 --- a/drivers/media/i2c/ti960-reg.h +++ b/drivers/media/i2c/ti960-reg.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2020 Intel Corporation */ +/* Copyright (C) 2022 Intel Corporation */ #ifndef TI960_REG_H #define TI960_REG_H @@ -90,7 +90,7 @@ static const struct ti960_register_write ti960_init_settings[] = { {0x33, 0x03}, {0x32, 0x12}, {0x33, 0x03}, - {0x20, 0x00}, + {0x20, 0xf0}, {0x21, 0x03}, }; @@ -135,7 +135,9 @@ static const struct ti960_register_write ti960_init_settings[] = { #define TI960_GPIO3_FSIN 0xa0 #define TI960_GPIO2_MASK 0x0f #define TI960_GPIO3_MASK 0xf0 +#define TI960_MIPI_400MBPS 0x3 #define TI960_MIPI_800MBPS 0x2 +#define TI960_MIPI_1200MBPS 0x1 #define TI960_MIPI_1600MBPS 0x0 #define TI960_CSI_ENABLE 0x1 #define TI960_CSI_CONTS_CLOCK 0x2 diff --git a/drivers/media/i2c/ti964.c b/drivers/media/i2c/ti964.c index 579a0fcead04..73df421e82fd 100644 --- a/drivers/media/i2c/ti964.c +++ b/drivers/media/i2c/ti964.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (C) 2016 - 2020 Intel Corporation +// Copyright (C) 2016 - 2022 Intel Corporation #include #include @@ -283,8 +283,12 @@ static int ti964_set_routing(struct v4l2_subdev *sd, } static int ti964_enum_mbus_code(struct v4l2_subdev *sd, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_mbus_code_enum *code) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif + struct v4l2_subdev_mbus_code_enum *code) { struct ti964 *va = to_ti964(sd); const uint32_t *supported_code = @@ -369,21 +373,33 @@ static int ti964_get_frame_desc(struct v4l2_subdev *sd, static struct v4l2_mbus_framefmt * __ti964_get_ffmt(struct v4l2_subdev *subdev, +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif unsigned int pad, unsigned int which, unsigned int stream) { struct ti964 *va = to_ti964(subdev); if (which == V4L2_SUBDEV_FORMAT_TRY) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) return v4l2_subdev_get_try_format(subdev, cfg, pad); +#else + return v4l2_subdev_get_try_format(subdev, sd_state, pad); +#endif else return &va->ffmts[pad][stream]; } static int ti964_get_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif + struct v4l2_subdev_format *fmt) { struct ti964 *va = to_ti964(subdev); @@ -391,8 +407,13 @@ static int ti964_get_format(struct v4l2_subdev *subdev, return -EINVAL; mutex_lock(&va->mutex); +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) fmt->format = *__ti964_get_ffmt(subdev, cfg, fmt->pad, - fmt->which, fmt->stream); + fmt->which, fmt->stream); +#else + fmt->format = *__ti964_get_ffmt(subdev, sd_state, fmt->pad, + fmt->which, fmt->stream); +#endif mutex_unlock(&va->mutex); dev_dbg(subdev->dev, "subdev_format: which: %s, pad: %d, stream: %d.\n", @@ -407,8 +428,12 @@ static int ti964_get_format(struct v4l2_subdev *subdev, } static int ti964_set_format(struct v4l2_subdev *subdev, - struct v4l2_subdev_pad_config *cfg, - struct v4l2_subdev_format *fmt) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) + struct v4l2_subdev_pad_config *cfg, +#else + struct v4l2_subdev_state *sd_state, +#endif + struct v4l2_subdev_format *fmt) { struct ti964 *va = to_ti964(subdev); const struct ti964_csi_data_format *csi_format; @@ -421,8 +446,13 @@ static int ti964_set_format(struct v4l2_subdev *subdev, fmt->format.code); mutex_lock(&va->mutex); +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) ffmt = __ti964_get_ffmt(subdev, cfg, fmt->pad, fmt->which, - fmt->stream); + fmt->stream); +#else + ffmt = __ti964_get_ffmt(subdev, sd_state, fmt->pad, fmt->which, + fmt->stream); +#endif if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { ffmt->width = fmt->format.width; @@ -441,9 +471,13 @@ static int ti964_set_format(struct v4l2_subdev *subdev, static int ti964_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 14, 0) struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_get_try_format(subdev, fh->pad, 0); - +#else + struct v4l2_mbus_framefmt *try_fmt = + v4l2_subdev_get_try_format(subdev, fh->state, 0); +#endif struct v4l2_subdev_format fmt = { .which = V4L2_SUBDEV_FORMAT_TRY, .pad = TI964_PAD_SOURCE, diff --git a/drivers/media/pci/intel/Kconfig b/drivers/media/pci/intel/Kconfig index d234797dd939..50d70ef17170 100644 --- a/drivers/media/pci/intel/Kconfig +++ b/drivers/media/pci/intel/Kconfig @@ -46,13 +46,13 @@ config VIDEO_INTEL_IPU_WERROR If in doubt, say "N". config VIDEO_INTEL_IPU_USE_PLATFORMDATA - tristate "Enable platform data" + bool "Enable platform data" default y help Enalbe platform data in IPU. config VIDEO_INTEL_IPU_PDATA_DYNAMIC_LOADING - tristate "Enable platform data dynamic loading" + bool "Enable platform data dynamic loading" depends on VIDEO_INTEL_IPU_USE_PLATFORMDATA default n help diff --git a/drivers/media/pci/intel/ipu-bus.c b/drivers/media/pci/intel/ipu-bus.c index b4778dea5420..8231bbe94040 100644 --- a/drivers/media/pci/intel/ipu-bus.c +++ b/drivers/media/pci/intel/ipu-bus.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (C) 2013 - 2020 Intel Corporation +// Copyright (C) 2013 - 2022 Intel Corporation #include #include @@ -100,6 +100,7 @@ static int ipu_bus_probe(struct device *dev) } rval = pm_runtime_get_sync(&adev->dev); if (rval < 0) { + pm_runtime_put(&adev->dev); dev_err(&adev->dev, "Failed to get runtime PM\n"); goto out_err; } @@ -148,18 +149,21 @@ static struct mutex ipu_bus_mutex; static void ipu_bus_release(struct device *dev) { + struct ipu_bus_device *adev = to_ipu_bus_device(dev); + + kfree(adev); } -struct ipu_bus_device *ipu_bus_add_device(struct pci_dev *pdev, - struct device *parent, void *pdata, - struct ipu_buttress_ctrl *ctrl, - char *name, unsigned int nr) +struct ipu_bus_device *ipu_bus_initialize_device(struct pci_dev *pdev, + struct device *parent, + void *pdata, + struct ipu_buttress_ctrl *ctrl, + char *name, unsigned int nr) { struct ipu_bus_device *adev; struct ipu_device *isp = pci_get_drvdata(pdev); - int rval; - adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL); + adev = kzalloc(sizeof(*adev), GFP_KERNEL); if (!adev) return ERR_PTR(-ENOMEM); @@ -183,20 +187,29 @@ struct ipu_bus_device *ipu_bus_add_device(struct pci_dev *pdev, mutex_init(&adev->resume_lock); dev_set_name(&adev->dev, "%s%d", name, nr); - rval = device_register(&adev->dev); + device_initialize(&adev->dev); + pm_runtime_forbid(&adev->dev); + pm_runtime_enable(&adev->dev); + + return adev; +} + +int ipu_bus_add_device(struct ipu_bus_device *adev) +{ + int rval; + + rval = device_add(&adev->dev); if (rval) { put_device(&adev->dev); - return ERR_PTR(rval); + return rval; } mutex_lock(&ipu_bus_mutex); - list_add(&adev->list, &isp->devices); + list_add(&adev->list, &adev->isp->devices); mutex_unlock(&ipu_bus_mutex); pm_runtime_allow(&adev->dev); - pm_runtime_enable(&adev->dev); - - return adev; + return 0; } void ipu_bus_del_devices(struct pci_dev *pdev) diff --git a/drivers/media/pci/intel/ipu-bus.h b/drivers/media/pci/intel/ipu-bus.h index 1108cd377705..d5794457a3d6 100644 --- a/drivers/media/pci/intel/ipu-bus.h +++ b/drivers/media/pci/intel/ipu-bus.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ -/* Copyright (C) 2013 - 2020 Intel Corporation */ +/* Copyright (C) 2013 - 2022 Intel Corporation */ #ifndef IPU_BUS_H #define IPU_BUS_H @@ -43,10 +43,12 @@ struct ipu_bus_driver { #define to_ipu_bus_driver(_drv) container_of(_drv, struct ipu_bus_driver, drv) -struct ipu_bus_device *ipu_bus_add_device(struct pci_dev *pdev, - struct device *parent, void *pdata, - struct ipu_buttress_ctrl *ctrl, - char *name, unsigned int nr); +struct ipu_bus_device *ipu_bus_initialize_device(struct pci_dev *pdev, + struct device *parent, + void *pdata, + struct ipu_buttress_ctrl *ctrl, + char *name, unsigned int nr); +int ipu_bus_add_device(struct ipu_bus_device *adev); void ipu_bus_del_devices(struct pci_dev *pdev); int ipu_bus_register_driver(struct ipu_bus_driver *adrv); diff --git a/drivers/media/pci/intel/ipu-isys-queue.c b/drivers/media/pci/intel/ipu-isys-queue.c index bee73b6a7f74..60460a814367 100644 --- a/drivers/media/pci/intel/ipu-isys-queue.c +++ b/drivers/media/pci/intel/ipu-isys-queue.c @@ -171,7 +171,7 @@ static void buf_cleanup(struct vb2_buffer *vb) __func__); if (aq->buf_cleanup) - return aq->buf_cleanup(vb); + aq->buf_cleanup(vb); } /* diff --git a/drivers/media/pci/intel/ipu-isys.c b/drivers/media/pci/intel/ipu-isys.c index d4b99ddd06c4..549231ab4452 100644 --- a/drivers/media/pci/intel/ipu-isys.c +++ b/drivers/media/pci/intel/ipu-isys.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (C) 2013 - 2021 Intel Corporation +// Copyright (C) 2013 - 2022 Intel Corporation #include #include @@ -361,9 +361,16 @@ static int isys_register_ext_subdev(struct ipu_isys *isys, sd_info->i2c.i2c_adapter_bdf, sizeof(sd_info->i2c.i2c_adapter_bdf)); if (bus < 0) { - dev_err(&isys->adev->dev, "Failed to find adapter!"); + dev_err(&isys->adev->dev, + "getting i2c bus id for adapter %d (bdf %s) failed", + sd_info->i2c.i2c_adapter_id, + sd_info->i2c.i2c_adapter_bdf); return -ENOENT; } + dev_info(&isys->adev->dev, + "got i2c bus id %d for adapter %d (bdf %s)", bus, + sd_info->i2c.i2c_adapter_id, + sd_info->i2c.i2c_adapter_bdf); adapter = i2c_get_adapter(bus); if (!adapter) { dev_warn(&isys->adev->dev, "can't find adapter\n"); @@ -610,7 +617,7 @@ static int isys_fwnode_parse(struct device *dev, return 0; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) && LINUX_VERSION_CODE != KERNEL_VERSION(5, 15, 71) +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0) static int isys_notifier_init(struct ipu_isys *isys) { struct ipu_device *isp = isys->adev->isp; diff --git a/drivers/media/pci/intel/ipu-psys.c b/drivers/media/pci/intel/ipu-psys.c index 93dac857f0f7..9c0c3ca31a92 100644 --- a/drivers/media/pci/intel/ipu-psys.c +++ b/drivers/media/pci/intel/ipu-psys.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (C) 2013 - 2020 Intel Corporation +// Copyright (C) 2013 - 2022 Intel Corporation #include #include @@ -427,8 +427,7 @@ static int ipu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf, return -ENOTTY; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 255) \ - || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 71) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 70) static int ipu_dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map) { struct dma_buf_attachment *attach; @@ -499,8 +498,7 @@ static void *ipu_dma_buf_vmap(struct dma_buf *dmabuf) } #endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 255) \ - || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 71) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 70) static void ipu_dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map) { struct dma_buf_attachment *attach; @@ -619,8 +617,7 @@ static inline void ipu_psys_kbuf_unmap(struct ipu_psys_kbuffer *kbuf) return; kbuf->valid = false; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 255) \ - || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 71) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 70) if (kbuf->kaddr) { struct iosys_map dmap; @@ -765,8 +762,7 @@ int ipu_psys_mapbuf_locked(int fd, struct ipu_psys_fh *fh, { struct ipu_psys *psys = fh->psys; struct dma_buf *dbuf; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 255) \ - || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 71) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 70) struct iosys_map dmap; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) && LINUX_VERSION_CODE != KERNEL_VERSION(5, 10, 46) struct dma_buf_map dmap; @@ -1498,6 +1494,10 @@ static int ipu_psys_probe(struct ipu_bus_device *adev) unsigned int minor; int i, rval = -E2BIG; + /* firmware is not ready, so defer the probe */ + if (!isp->pkg_dir) + return -EPROBE_DEFER; + rval = ipu_mmu_hw_init(adev->mmu); if (rval) return rval; @@ -1821,6 +1821,6 @@ MODULE_AUTHOR("Zaikuo Wang "); MODULE_AUTHOR("Yunliang Ding "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Intel ipu processing system driver"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0) || LINUX_VERSION_CODE == KERNEL_VERSION(5, 15, 71) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0) MODULE_IMPORT_NS(DMA_BUF); #endif diff --git a/drivers/media/pci/intel/ipu.c b/drivers/media/pci/intel/ipu.c index 9ef4423a0320..5981b08ca4e3 100644 --- a/drivers/media/pci/intel/ipu.c +++ b/drivers/media/pci/intel/ipu.c @@ -70,6 +70,7 @@ static struct ipu_bus_device *ipu_isys_init(struct pci_dev *pdev, #if IS_ENABLED(CONFIG_INTEL_IPU6_ACPI) struct ipu_isys_subdev_pdata *acpi_pdata; #endif + int ret; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -85,28 +86,39 @@ static struct ipu_bus_device *ipu_isys_init(struct pci_dev *pdev, if (ipu_ver == IPU_VER_6SE) ctrl->ratio = IPU6SE_IS_FREQ_CTL_DEFAULT_RATIO; - isys = ipu_bus_add_device(pdev, parent, pdata, ctrl, - IPU_ISYS_NAME, nr); - if (IS_ERR(isys)) - return ERR_PTR(-ENOMEM); - + isys = ipu_bus_initialize_device(pdev, parent, pdata, ctrl, + IPU_ISYS_NAME, nr); + if (IS_ERR(isys)) { + dev_err_probe(&pdev->dev, PTR_ERR(isys), + "ipu_bus_add_device(isys) failed\n"); + return ERR_CAST(isys); + } #if IS_ENABLED(CONFIG_INTEL_IPU6_ACPI) if (!spdata) { dev_err(&pdev->dev, "No subdevice info provided"); - ipu_get_acpi_devices(isys, &isys->dev, &acpi_pdata, NULL, isys_init_acpi_add_device); + ipu_get_acpi_devices(isys, &isys->dev, &acpi_pdata, NULL, + isys_init_acpi_add_device); pdata->spdata = acpi_pdata; } else { dev_dbg(&pdev->dev, "Subdevice info found"); - ipu_get_acpi_devices(isys, &isys->dev, &acpi_pdata, &spdata, isys_init_acpi_add_device); + ipu_get_acpi_devices(isys, &isys->dev, &acpi_pdata, &spdata, + isys_init_acpi_add_device); } #endif isys->mmu = ipu_mmu_init(&pdev->dev, base, ISYS_MMID, &ipdata->hw_variant); - if (IS_ERR(isys->mmu)) - return ERR_PTR(-ENOMEM); + if (IS_ERR(isys->mmu)) { + dev_err_probe(&pdev->dev, PTR_ERR(isys), + "ipu_mmu_init(isys->mmu) failed\n"); + return ERR_CAST(isys->mmu); + } isys->mmu->dev = &isys->dev; + ret = ipu_bus_add_device(isys); + if (ret) + return ERR_PTR(ret); + return isys; } @@ -119,6 +131,7 @@ static struct ipu_bus_device *ipu_psys_init(struct pci_dev *pdev, { struct ipu_bus_device *psys; struct ipu_psys_pdata *pdata; + int ret; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) @@ -127,18 +140,28 @@ static struct ipu_bus_device *ipu_psys_init(struct pci_dev *pdev, pdata->base = base; pdata->ipdata = ipdata; - psys = ipu_bus_add_device(pdev, parent, pdata, ctrl, - IPU_PSYS_NAME, nr); - if (IS_ERR(psys)) - return ERR_PTR(-ENOMEM); + psys = ipu_bus_initialize_device(pdev, parent, pdata, ctrl, + IPU_PSYS_NAME, nr); + if (IS_ERR(psys)) { + dev_err_probe(&pdev->dev, PTR_ERR(psys), + "ipu_bus_add_device(psys) failed\n"); + return ERR_CAST(psys); + } psys->mmu = ipu_mmu_init(&pdev->dev, base, PSYS_MMID, &ipdata->hw_variant); - if (IS_ERR(psys->mmu)) - return ERR_PTR(-ENOMEM); + if (IS_ERR(psys->mmu)) { + dev_err_probe(&pdev->dev, PTR_ERR(psys), + "ipu_mmu_init(psys->mmu) failed\n"); + return ERR_CAST(psys->mmu); + } psys->mmu->dev = &psys->dev; + ret = ipu_bus_add_device(psys); + if (ret) + return ERR_PTR(ret); + return psys; } diff --git a/drivers/media/pci/intel/ipu6/Makefile b/drivers/media/pci/intel/ipu6/Makefile index d6acf6ad687d..51a18376c965 100644 --- a/drivers/media/pci/intel/ipu6/Makefile +++ b/drivers/media/pci/intel/ipu6/Makefile @@ -5,9 +5,9 @@ ifneq ($(EXTERNAL_BUILD), 1) srcpath := $(srctree) endif -ccflags-y += -DIPU_VC_SUPPORT -DIPU_HAS_S2M -DIPU_TPG_FRAME_SYNC -DIPU_PSYS_GPC \ +ccflags-y += -DIPU_HAS_S2M -DIPU_TPG_FRAME_SYNC -DIPU_PSYS_GPC \ -DIPU_ISYS_GPC -ccflags-y += -DIPU_META_DATA_SUPPORT -DI2C_DYNAMIC +ccflags-y += -DI2C_DYNAMIC ccflags-y += -DIPU_ISYS_RESET intel-ipu6-objs += ../ipu.o \ diff --git a/drivers/media/platform/intel/Kconfig b/drivers/media/platform/intel/Kconfig index f56a0aad5faa..c87ba10d14dc 100644 --- a/drivers/media/platform/intel/Kconfig +++ b/drivers/media/platform/intel/Kconfig @@ -1,11 +1,11 @@ config INTEL_IPU6_TGLRVP_PDATA - tristate "Enable built in platform data for TGL RVP" + bool "Enable built in platform data for TGL RVP" depends on MEDIA_CAMERA_SUPPORT help Pre-ACPI system platform data is compiled inside kernel config INTEL_IPU6_ADLRVP_PDATA - tristate "Enable built in platform data for ADL RVP" + bool "Enable built in platform data for ADL RVP" depends on MEDIA_CAMERA_SUPPORT help Pre-ACPI system platform data is compiled inside kernel diff --git a/drivers/media/platform/intel/ipu6-adlrvp-pdata.c b/drivers/media/platform/intel/ipu6-adlrvp-pdata.c index f7191ac8486a..d1038c5d9037 100644 --- a/drivers/media/platform/intel/ipu6-adlrvp-pdata.c +++ b/drivers/media/platform/intel/ipu6-adlrvp-pdata.c @@ -7,14 +7,28 @@ #include #include +#if IS_ENABLED(CONFIG_VIDEO_TI960) #include +#endif +#if IS_ENABLED(CONFIG_VIDEO_AR0234) #include +#endif +#if IS_ENABLED(CONFIG_VIDEO_IMX390) #include +#endif +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) #include +#endif +#if IS_ENABLED(CONFIG_VIDEO_D4XX) #include +#endif #include "ipu.h" +#if IS_ENABLED(CONFIG_VIDEO_AR0234) +#define AR0234_LANES 2 +#define AR0234_I2C_ADDRESS 0x10 + #if IS_ENABLED(CONFIG_VIDEO_INTEL_IPU_USE_PLATFORMDATA) \ && IS_ENABLED(CONFIG_VIDEO_INTEL_IPU_PDATA_DYNAMIC_LOADING) static void ar0234_fixup_spdata(const void *spdata_rep, void *spdata) @@ -33,29 +47,8 @@ static void ar0234_fixup_spdata(const void *spdata_rep, void *spdata) platform->suffix = rep->suffix; } } - -static void lt6911uxc_fixup_spdata(const void *spdata_rep, void *spdata) -{ - const struct ipu_spdata_rep *rep = spdata_rep; - struct lt6911uxc_platform_data *platform = spdata; - - if (spdata_rep && spdata) { - platform->port = rep->port_n; - platform->lanes = rep->lanes; - platform->i2c_slave_address = rep->slave_addr_n; - platform->gpios[0] = rep->gpios[0]; - platform->irq_pin = rep->irq_pin; - platform->irq_pin_flags = rep->irq_pin_flags; - strcpy(platform->irq_pin_name, rep->irq_pin_name); - platform->suffix = rep->suffix; - } -} - #endif -#define AR0234_LANES 2 -#define AR0234_I2C_ADDRESS 0x10 - static struct ipu_isys_csi2_config ar0234_csi2_cfg_1 = { .nlanes = AR0234_LANES, .port = 1, @@ -119,6 +112,7 @@ static struct ipu_isys_subdev_info ar0234_sd_2 = { .fixup_spdata = ar0234_fixup_spdata, #endif }; +#endif #if IS_ENABLED(CONFIG_VIDEO_IMX390) #define IMX390_LANES 4 @@ -225,10 +219,9 @@ static struct ipu_isys_subdev_info imx390_sd_4 = { #endif #if IS_ENABLED(CONFIG_VIDEO_TI960) -#define TI960_I2C_ADAPTER 2 -#define TI960_I2C_ADAPTER_2 4 #define TI960_LANES 4 +#if IS_ENABLED(CONFIG_VIDEO_IMX390) #define IMX390A_ADDRESS 0x44 #define IMX390B_ADDRESS 0x45 #define IMX390C_ADDRESS 0x46 @@ -254,12 +247,18 @@ static struct ti960_subdev_pdata imx390_d3cm_pdata_stub = { .module_name = "imx390", .fsin = 3, /* gpio 3 used for FSIN */ }; +#endif -static struct ipu_isys_csi2_config ti960_csi2_cfg = { +static struct ipu_isys_csi2_config ti960_csi2_cfg_1 = { .nlanes = TI960_LANES, .port = 1, }; +static struct ipu_isys_csi2_config ti960_csi2_cfg_2 = { + .nlanes = TI960_LANES, + .port = 2, +}; + static struct ti960_subdev_info ti960_subdevs[] = { #if IS_ENABLED(CONFIG_VIDEO_IMX390) /* D3RCM */ @@ -355,34 +354,71 @@ static struct ti960_subdev_info ti960_subdevs[] = { #endif }; -static struct ti960_pdata ti960_pdata = { +static struct ti960_pdata ti960_pdata_1 = { .subdev_info = ti960_subdevs, .subdev_num = ARRAY_SIZE(ti960_subdevs), .reset_gpio = 0, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 12) - .FPD_gpio = 175, -#else - .FPD_gpio = 258, -#endif + .FPD_gpio = -1, .suffix = 'a', }; -static struct ipu_isys_subdev_info ti960_sd = { - .csi2 = &ti960_csi2_cfg, +static struct ti960_pdata ti960_pdata_2 = { + .subdev_info = ti960_subdevs, + .subdev_num = ARRAY_SIZE(ti960_subdevs), + .reset_gpio = 0, + .FPD_gpio = -1, + .suffix = 'b', +}; + +static struct ipu_isys_subdev_info ti960_sd_1 = { + .csi2 = &ti960_csi2_cfg_1, .i2c = { .board_info = { .type = "ti960", - .addr = TI960_I2C_ADDRESS, - .platform_data = &ti960_pdata, + .addr = TI960_I2C_ADDRESS_2, + .platform_data = &ti960_pdata_1, }, .i2c_adapter_bdf = "0000:00:15.1", } }; + +static struct ipu_isys_subdev_info ti960_sd_2 = { + .csi2 = &ti960_csi2_cfg_2, + .i2c = { + .board_info = { + .type = "ti960", + .addr = TI960_I2C_ADDRESS_2, + .platform_data = &ti960_pdata_2, + }, + .i2c_adapter_bdf = "0000:00:19.1", + } +}; #endif +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) #define LT6911UXC_LANES 4 #define LT6911UXC_I2C_ADDRESS 0x2B +#if IS_ENABLED(CONFIG_VIDEO_INTEL_IPU_USE_PLATFORMDATA) \ + && IS_ENABLED(CONFIG_VIDEO_INTEL_IPU_PDATA_DYNAMIC_LOADING) +static void lt6911uxc_fixup_spdata(const void *spdata_rep, void *spdata) +{ + const struct ipu_spdata_rep *rep = spdata_rep; + struct lt6911uxc_platform_data *platform = spdata; + + if (spdata_rep && spdata) { + platform->port = rep->port_n; + platform->lanes = rep->lanes; + platform->i2c_slave_address = rep->slave_addr_n; + platform->gpios[0] = rep->gpios[0]; + platform->irq_pin = rep->irq_pin; + platform->irq_pin_flags = rep->irq_pin_flags; + strcpy(platform->irq_pin_name, rep->irq_pin_name); + platform->suffix = rep->suffix; + } +} +#endif + static struct ipu_isys_csi2_config lt6911uxc_csi2_cfg_1 = { .nlanes = LT6911UXC_LANES, .port = 1, @@ -450,6 +486,7 @@ static struct ipu_isys_subdev_info lt6911uxc_sd_2 = { .fixup_spdata = lt6911uxc_fixup_spdata, #endif }; +#endif #if IS_ENABLED(CONFIG_VIDEO_D4XX) #define D4XX_LANES 2 @@ -548,14 +585,18 @@ static struct ipu_isys_clk_mapping clk_mapping[] = { static struct ipu_isys_subdev_pdata pdata = { .subdevs = (struct ipu_isys_subdev_info *[]) { +#if IS_ENABLED(CONFIG_VIDEO_AR0234) &ar0234_sd_1, &ar0234_sd_2, +#endif #if IS_ENABLED(CONFIG_VIDEO_TI960) - //&ti960_sd, - //&ti960_sd_2, + &ti960_sd_1, + &ti960_sd_2, #endif +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) <6911uxc_sd_1, <6911uxc_sd_2, +#endif #if IS_ENABLED(CONFIG_VIDEO_D4XX) &d4xx_sd_0, &d4xx_sd_1, diff --git a/drivers/media/platform/intel/ipu6-tglrvp-pdata.c b/drivers/media/platform/intel/ipu6-tglrvp-pdata.c index 93d49faa5612..c1a4cad18d68 100644 --- a/drivers/media/platform/intel/ipu6-tglrvp-pdata.c +++ b/drivers/media/platform/intel/ipu6-tglrvp-pdata.c @@ -84,6 +84,8 @@ static void ar0234_fixup_spdata(const void *spdata_rep, void *spdata) } #endif +#if IS_ENABLED(CONFIG_VIDEO_AR0234) + #define AR0234_LANES 2 #define AR0234_I2C_ADDRESS 0x10 #define AR0234_I2C_ADDRESS_2 0x18 @@ -217,6 +219,7 @@ static struct ipu_isys_subdev_info ar0234_sd_4 = { .fixup_spdata = ar0234_fixup_spdata, #endif }; +#endif #if IS_ENABLED(CONFIG_VIDEO_IMX390) #define IMX390_LANES 4 @@ -498,6 +501,8 @@ static struct ipu_isys_subdev_info ti960_sd_2 = { }; #endif +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) + #define LT6911UXC_LANES 4 #define LT6911UXC_I2C_ADDRESS 0x2B @@ -588,6 +593,7 @@ static struct ipu_isys_subdev_info lt6911uxc_sd_2 = { .i2c_adapter_bdf = "0000:00:19.1", }, }; +#endif static struct ipu_isys_clk_mapping clk_mapping[] = { { CLKDEV_INIT(NULL, NULL, NULL), NULL } @@ -600,12 +606,14 @@ static struct ipu_isys_subdev_pdata pdata = { &dw9714_sd_1, &ov8856_sd_2, #endif +#if IS_ENABLED(CONFIG_VIDEO_AR0234) &ar0234_sd_1, &ar0234_sd_2, #if !IS_ENABLED(CONFIG_VIDEO_LT6911UXC) &ar0234_sd_3, #endif &ar0234_sd_4, +#endif #if IS_ENABLED(CONFIG_VIDEO_IMX390) &imx390_sd_1, &imx390_sd_2, @@ -616,9 +624,11 @@ static struct ipu_isys_subdev_pdata pdata = { &ti960_sd, &ti960_sd_2, #endif +#if IS_ENABLED(CONFIG_VIDEO_LT6911UXC) <6911uxc_sd_0, //Auxiliary port for 4k60fps <6911uxc_sd_1, <6911uxc_sd_2, +#endif NULL, }, .clk_map = clk_mapping,