162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR MIT) 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Rockchip ISP1 Driver - CSI-2 Receiver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2019 Collabora, Ltd. 662306a36Sopenharmony_ci * Copyright (C) 2022 Ideas on Board 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. 962306a36Sopenharmony_ci * Copyright (C) 2017 Rockchip Electronics Co., Ltd. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/delay.h> 1362306a36Sopenharmony_ci#include <linux/device.h> 1462306a36Sopenharmony_ci#include <linux/lockdep.h> 1562306a36Sopenharmony_ci#include <linux/phy/phy.h> 1662306a36Sopenharmony_ci#include <linux/phy/phy-mipi-dphy.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <media/v4l2-ctrls.h> 1962306a36Sopenharmony_ci#include <media/v4l2-fwnode.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include "rkisp1-common.h" 2262306a36Sopenharmony_ci#include "rkisp1-csi.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define RKISP1_CSI_DEV_NAME RKISP1_DRIVER_NAME "_csi" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define RKISP1_CSI_DEF_FMT MEDIA_BUS_FMT_SRGGB10_1X10 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic inline struct rkisp1_csi *to_rkisp1_csi(struct v4l2_subdev *sd) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci return container_of(sd, struct rkisp1_csi, sd); 3162306a36Sopenharmony_ci} 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic struct v4l2_mbus_framefmt * 3462306a36Sopenharmony_cirkisp1_csi_get_pad_fmt(struct rkisp1_csi *csi, 3562306a36Sopenharmony_ci struct v4l2_subdev_state *sd_state, 3662306a36Sopenharmony_ci unsigned int pad, u32 which) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci struct v4l2_subdev_state state = { 3962306a36Sopenharmony_ci .pads = csi->pad_cfg 4062306a36Sopenharmony_ci }; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci lockdep_assert_held(&csi->lock); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci if (which == V4L2_SUBDEV_FORMAT_TRY) 4562306a36Sopenharmony_ci return v4l2_subdev_get_try_format(&csi->sd, sd_state, pad); 4662306a36Sopenharmony_ci else 4762306a36Sopenharmony_ci return v4l2_subdev_get_try_format(&csi->sd, &state, pad); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ciint rkisp1_csi_link_sensor(struct rkisp1_device *rkisp1, struct v4l2_subdev *sd, 5162306a36Sopenharmony_ci struct rkisp1_sensor_async *s_asd, 5262306a36Sopenharmony_ci unsigned int source_pad) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci struct rkisp1_csi *csi = &rkisp1->csi; 5562306a36Sopenharmony_ci int ret; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci s_asd->pixel_rate_ctrl = v4l2_ctrl_find(sd->ctrl_handler, 5862306a36Sopenharmony_ci V4L2_CID_PIXEL_RATE); 5962306a36Sopenharmony_ci if (!s_asd->pixel_rate_ctrl) { 6062306a36Sopenharmony_ci dev_err(rkisp1->dev, "No pixel rate control in subdev %s\n", 6162306a36Sopenharmony_ci sd->name); 6262306a36Sopenharmony_ci return -EINVAL; 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci /* Create the link from the sensor to the CSI receiver. */ 6662306a36Sopenharmony_ci ret = media_create_pad_link(&sd->entity, source_pad, 6762306a36Sopenharmony_ci &csi->sd.entity, RKISP1_CSI_PAD_SINK, 6862306a36Sopenharmony_ci !s_asd->index ? MEDIA_LNK_FL_ENABLED : 0); 6962306a36Sopenharmony_ci if (ret) { 7062306a36Sopenharmony_ci dev_err(csi->rkisp1->dev, "failed to link src pad of %s\n", 7162306a36Sopenharmony_ci sd->name); 7262306a36Sopenharmony_ci return ret; 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci return 0; 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic int rkisp1_csi_config(struct rkisp1_csi *csi, 7962306a36Sopenharmony_ci const struct rkisp1_sensor_async *sensor) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = csi->rkisp1; 8262306a36Sopenharmony_ci unsigned int lanes = sensor->lanes; 8362306a36Sopenharmony_ci u32 mipi_ctrl; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (lanes < 1 || lanes > 4) 8662306a36Sopenharmony_ci return -EINVAL; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci mipi_ctrl = RKISP1_CIF_MIPI_CTRL_NUM_LANES(lanes - 1) | 8962306a36Sopenharmony_ci RKISP1_CIF_MIPI_CTRL_SHUTDOWNLANES(0xf) | 9062306a36Sopenharmony_ci RKISP1_CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP | 9162306a36Sopenharmony_ci RKISP1_CIF_MIPI_CTRL_CLOCKLANE_ENA; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_CTRL, mipi_ctrl); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci /* V12 could also use a newer csi2-host, but we don't want that yet */ 9662306a36Sopenharmony_ci if (rkisp1->info->isp_ver == RKISP1_V12) 9762306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_ISP_CSI0_CTRL0, 0); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* Configure Data Type and Virtual Channel */ 10062306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMG_DATA_SEL, 10162306a36Sopenharmony_ci RKISP1_CIF_MIPI_DATA_SEL_DT(csi->sink_fmt->mipi_dt) | 10262306a36Sopenharmony_ci RKISP1_CIF_MIPI_DATA_SEL_VC(0)); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* Clear MIPI interrupts */ 10562306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_ICR, ~0); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* 10862306a36Sopenharmony_ci * Disable RKISP1_CIF_MIPI_ERR_DPHY interrupt here temporary for 10962306a36Sopenharmony_ci * isp bus may be dead when switch isp. 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC, 11262306a36Sopenharmony_ci RKISP1_CIF_MIPI_FRAME_END | RKISP1_CIF_MIPI_ERR_CSI | 11362306a36Sopenharmony_ci RKISP1_CIF_MIPI_ERR_DPHY | 11462306a36Sopenharmony_ci RKISP1_CIF_MIPI_SYNC_FIFO_OVFLW(0x03) | 11562306a36Sopenharmony_ci RKISP1_CIF_MIPI_ADD_DATA_OVFLW); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci dev_dbg(rkisp1->dev, "\n MIPI_CTRL 0x%08x\n" 11862306a36Sopenharmony_ci " MIPI_IMG_DATA_SEL 0x%08x\n" 11962306a36Sopenharmony_ci " MIPI_STATUS 0x%08x\n" 12062306a36Sopenharmony_ci " MIPI_IMSC 0x%08x\n", 12162306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL), 12262306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMG_DATA_SEL), 12362306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_MIPI_STATUS), 12462306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC)); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci return 0; 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic void rkisp1_csi_enable(struct rkisp1_csi *csi) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = csi->rkisp1; 13262306a36Sopenharmony_ci u32 val; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL); 13562306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_CTRL, 13662306a36Sopenharmony_ci val | RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA); 13762306a36Sopenharmony_ci} 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic void rkisp1_csi_disable(struct rkisp1_csi *csi) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = csi->rkisp1; 14262306a36Sopenharmony_ci u32 val; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci /* Mask MIPI interrupts. */ 14562306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC, 0); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci /* Flush posted writes */ 14862306a36Sopenharmony_ci rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC); 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci /* 15162306a36Sopenharmony_ci * Wait until the IRQ handler has ended. The IRQ handler may get called 15262306a36Sopenharmony_ci * even after this, but it will return immediately as the MIPI 15362306a36Sopenharmony_ci * interrupts have been masked. 15462306a36Sopenharmony_ci */ 15562306a36Sopenharmony_ci synchronize_irq(rkisp1->irqs[RKISP1_IRQ_MIPI]); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci /* Clear MIPI interrupt status */ 15862306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_ICR, ~0); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_CTRL); 16162306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_CTRL, 16262306a36Sopenharmony_ci val & (~RKISP1_CIF_MIPI_CTRL_OUTPUT_ENA)); 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic int rkisp1_csi_start(struct rkisp1_csi *csi, 16662306a36Sopenharmony_ci const struct rkisp1_sensor_async *sensor) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = csi->rkisp1; 16962306a36Sopenharmony_ci union phy_configure_opts opts; 17062306a36Sopenharmony_ci struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy; 17162306a36Sopenharmony_ci s64 pixel_clock; 17262306a36Sopenharmony_ci int ret; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci ret = rkisp1_csi_config(csi, sensor); 17562306a36Sopenharmony_ci if (ret) 17662306a36Sopenharmony_ci return ret; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci pixel_clock = v4l2_ctrl_g_ctrl_int64(sensor->pixel_rate_ctrl); 17962306a36Sopenharmony_ci if (!pixel_clock) { 18062306a36Sopenharmony_ci dev_err(rkisp1->dev, "Invalid pixel rate value\n"); 18162306a36Sopenharmony_ci return -EINVAL; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci phy_mipi_dphy_get_default_config(pixel_clock, csi->sink_fmt->bus_width, 18562306a36Sopenharmony_ci sensor->lanes, cfg); 18662306a36Sopenharmony_ci phy_set_mode(csi->dphy, PHY_MODE_MIPI_DPHY); 18762306a36Sopenharmony_ci phy_configure(csi->dphy, &opts); 18862306a36Sopenharmony_ci phy_power_on(csi->dphy); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci rkisp1_csi_enable(csi); 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci /* 19362306a36Sopenharmony_ci * CIF spec says to wait for sufficient time after enabling 19462306a36Sopenharmony_ci * the MIPI interface and before starting the sensor output. 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_ci usleep_range(1000, 1200); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci return 0; 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic void rkisp1_csi_stop(struct rkisp1_csi *csi) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci rkisp1_csi_disable(csi); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci phy_power_off(csi->dphy); 20662306a36Sopenharmony_ci} 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ciirqreturn_t rkisp1_csi_isr(int irq, void *ctx) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci struct device *dev = ctx; 21162306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); 21262306a36Sopenharmony_ci u32 val, status; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (!rkisp1->irqs_enabled) 21562306a36Sopenharmony_ci return IRQ_NONE; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci status = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_MIS); 21862306a36Sopenharmony_ci if (!status) 21962306a36Sopenharmony_ci return IRQ_NONE; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_ICR, status); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* 22462306a36Sopenharmony_ci * Disable DPHY errctrl interrupt, because this dphy 22562306a36Sopenharmony_ci * erctrl signal is asserted until the next changes 22662306a36Sopenharmony_ci * of line state. This time is may be too long and cpu 22762306a36Sopenharmony_ci * is hold in this interrupt. 22862306a36Sopenharmony_ci */ 22962306a36Sopenharmony_ci if (status & RKISP1_CIF_MIPI_ERR_CTRL(0x0f)) { 23062306a36Sopenharmony_ci val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC); 23162306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC, 23262306a36Sopenharmony_ci val & ~RKISP1_CIF_MIPI_ERR_CTRL(0x0f)); 23362306a36Sopenharmony_ci rkisp1->csi.is_dphy_errctrl_disabled = true; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* 23762306a36Sopenharmony_ci * Enable DPHY errctrl interrupt again, if mipi have receive 23862306a36Sopenharmony_ci * the whole frame without any error. 23962306a36Sopenharmony_ci */ 24062306a36Sopenharmony_ci if (status == RKISP1_CIF_MIPI_FRAME_END) { 24162306a36Sopenharmony_ci /* 24262306a36Sopenharmony_ci * Enable DPHY errctrl interrupt again, if mipi have receive 24362306a36Sopenharmony_ci * the whole frame without any error. 24462306a36Sopenharmony_ci */ 24562306a36Sopenharmony_ci if (rkisp1->csi.is_dphy_errctrl_disabled) { 24662306a36Sopenharmony_ci val = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_IMSC); 24762306a36Sopenharmony_ci val |= RKISP1_CIF_MIPI_ERR_CTRL(0x0f); 24862306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MIPI_IMSC, val); 24962306a36Sopenharmony_ci rkisp1->csi.is_dphy_errctrl_disabled = false; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci } else { 25262306a36Sopenharmony_ci rkisp1->debug.mipi_error++; 25362306a36Sopenharmony_ci } 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci return IRQ_HANDLED; 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 25962306a36Sopenharmony_ci * Subdev pad operations 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic int rkisp1_csi_enum_mbus_code(struct v4l2_subdev *sd, 26362306a36Sopenharmony_ci struct v4l2_subdev_state *sd_state, 26462306a36Sopenharmony_ci struct v4l2_subdev_mbus_code_enum *code) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci struct rkisp1_csi *csi = to_rkisp1_csi(sd); 26762306a36Sopenharmony_ci unsigned int i; 26862306a36Sopenharmony_ci int pos = 0; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if (code->pad == RKISP1_CSI_PAD_SRC) { 27162306a36Sopenharmony_ci const struct v4l2_mbus_framefmt *sink_fmt; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci if (code->index) 27462306a36Sopenharmony_ci return -EINVAL; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci mutex_lock(&csi->lock); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci sink_fmt = rkisp1_csi_get_pad_fmt(csi, sd_state, 27962306a36Sopenharmony_ci RKISP1_CSI_PAD_SINK, 28062306a36Sopenharmony_ci code->which); 28162306a36Sopenharmony_ci code->code = sink_fmt->code; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci mutex_unlock(&csi->lock); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return 0; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci for (i = 0; ; i++) { 28962306a36Sopenharmony_ci const struct rkisp1_mbus_info *fmt = 29062306a36Sopenharmony_ci rkisp1_mbus_info_get_by_index(i); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci if (!fmt) 29362306a36Sopenharmony_ci return -EINVAL; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (!(fmt->direction & RKISP1_ISP_SD_SINK)) 29662306a36Sopenharmony_ci continue; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (code->index == pos) { 29962306a36Sopenharmony_ci code->code = fmt->mbus_code; 30062306a36Sopenharmony_ci return 0; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci pos++; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci return -EINVAL; 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic int rkisp1_csi_init_config(struct v4l2_subdev *sd, 31062306a36Sopenharmony_ci struct v4l2_subdev_state *sd_state) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci sink_fmt = v4l2_subdev_get_try_format(sd, sd_state, 31562306a36Sopenharmony_ci RKISP1_CSI_PAD_SINK); 31662306a36Sopenharmony_ci src_fmt = v4l2_subdev_get_try_format(sd, sd_state, 31762306a36Sopenharmony_ci RKISP1_CSI_PAD_SRC); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci sink_fmt->width = RKISP1_DEFAULT_WIDTH; 32062306a36Sopenharmony_ci sink_fmt->height = RKISP1_DEFAULT_HEIGHT; 32162306a36Sopenharmony_ci sink_fmt->field = V4L2_FIELD_NONE; 32262306a36Sopenharmony_ci sink_fmt->code = RKISP1_CSI_DEF_FMT; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci *src_fmt = *sink_fmt; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci return 0; 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic int rkisp1_csi_get_fmt(struct v4l2_subdev *sd, 33062306a36Sopenharmony_ci struct v4l2_subdev_state *sd_state, 33162306a36Sopenharmony_ci struct v4l2_subdev_format *fmt) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci struct rkisp1_csi *csi = to_rkisp1_csi(sd); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci mutex_lock(&csi->lock); 33662306a36Sopenharmony_ci fmt->format = *rkisp1_csi_get_pad_fmt(csi, sd_state, fmt->pad, 33762306a36Sopenharmony_ci fmt->which); 33862306a36Sopenharmony_ci mutex_unlock(&csi->lock); 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci return 0; 34162306a36Sopenharmony_ci} 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_cistatic int rkisp1_csi_set_fmt(struct v4l2_subdev *sd, 34462306a36Sopenharmony_ci struct v4l2_subdev_state *sd_state, 34562306a36Sopenharmony_ci struct v4l2_subdev_format *fmt) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci struct rkisp1_csi *csi = to_rkisp1_csi(sd); 34862306a36Sopenharmony_ci const struct rkisp1_mbus_info *mbus_info; 34962306a36Sopenharmony_ci struct v4l2_mbus_framefmt *sink_fmt, *src_fmt; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* The format on the source pad always matches the sink pad. */ 35262306a36Sopenharmony_ci if (fmt->pad == RKISP1_CSI_PAD_SRC) 35362306a36Sopenharmony_ci return rkisp1_csi_get_fmt(sd, sd_state, fmt); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci mutex_lock(&csi->lock); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci sink_fmt = rkisp1_csi_get_pad_fmt(csi, sd_state, RKISP1_CSI_PAD_SINK, 35862306a36Sopenharmony_ci fmt->which); 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci sink_fmt->code = fmt->format.code; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci mbus_info = rkisp1_mbus_info_get_by_code(sink_fmt->code); 36362306a36Sopenharmony_ci if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SINK)) { 36462306a36Sopenharmony_ci sink_fmt->code = RKISP1_CSI_DEF_FMT; 36562306a36Sopenharmony_ci mbus_info = rkisp1_mbus_info_get_by_code(sink_fmt->code); 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci sink_fmt->width = clamp_t(u32, fmt->format.width, 36962306a36Sopenharmony_ci RKISP1_ISP_MIN_WIDTH, 37062306a36Sopenharmony_ci RKISP1_ISP_MAX_WIDTH); 37162306a36Sopenharmony_ci sink_fmt->height = clamp_t(u32, fmt->format.height, 37262306a36Sopenharmony_ci RKISP1_ISP_MIN_HEIGHT, 37362306a36Sopenharmony_ci RKISP1_ISP_MAX_HEIGHT); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci fmt->format = *sink_fmt; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) 37862306a36Sopenharmony_ci csi->sink_fmt = mbus_info; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci /* Propagate the format to the source pad. */ 38162306a36Sopenharmony_ci src_fmt = rkisp1_csi_get_pad_fmt(csi, sd_state, RKISP1_CSI_PAD_SRC, 38262306a36Sopenharmony_ci fmt->which); 38362306a36Sopenharmony_ci *src_fmt = *sink_fmt; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci mutex_unlock(&csi->lock); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci return 0; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 39162306a36Sopenharmony_ci * Subdev video operations 39262306a36Sopenharmony_ci */ 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_cistatic int rkisp1_csi_s_stream(struct v4l2_subdev *sd, int enable) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci struct rkisp1_csi *csi = to_rkisp1_csi(sd); 39762306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = csi->rkisp1; 39862306a36Sopenharmony_ci struct rkisp1_sensor_async *source_asd; 39962306a36Sopenharmony_ci struct v4l2_async_connection *asc; 40062306a36Sopenharmony_ci struct media_pad *source_pad; 40162306a36Sopenharmony_ci struct v4l2_subdev *source; 40262306a36Sopenharmony_ci int ret; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if (!enable) { 40562306a36Sopenharmony_ci v4l2_subdev_call(csi->source, video, s_stream, false); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci rkisp1_csi_stop(csi); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci return 0; 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci source_pad = media_entity_remote_source_pad_unique(&sd->entity); 41362306a36Sopenharmony_ci if (IS_ERR(source_pad)) { 41462306a36Sopenharmony_ci dev_dbg(rkisp1->dev, "Failed to get source for CSI: %ld\n", 41562306a36Sopenharmony_ci PTR_ERR(source_pad)); 41662306a36Sopenharmony_ci return -EPIPE; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci source = media_entity_to_v4l2_subdev(source_pad->entity); 42062306a36Sopenharmony_ci if (!source) { 42162306a36Sopenharmony_ci /* This should really not happen, so is not worth a message. */ 42262306a36Sopenharmony_ci return -EPIPE; 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci asc = v4l2_async_connection_unique(source); 42662306a36Sopenharmony_ci if (!asc) 42762306a36Sopenharmony_ci return -EPIPE; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci source_asd = container_of(asc, struct rkisp1_sensor_async, asd); 43062306a36Sopenharmony_ci if (source_asd->mbus_type != V4L2_MBUS_CSI2_DPHY) 43162306a36Sopenharmony_ci return -EINVAL; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci mutex_lock(&csi->lock); 43462306a36Sopenharmony_ci ret = rkisp1_csi_start(csi, source_asd); 43562306a36Sopenharmony_ci mutex_unlock(&csi->lock); 43662306a36Sopenharmony_ci if (ret) 43762306a36Sopenharmony_ci return ret; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci ret = v4l2_subdev_call(source, video, s_stream, true); 44062306a36Sopenharmony_ci if (ret) { 44162306a36Sopenharmony_ci rkisp1_csi_stop(csi); 44262306a36Sopenharmony_ci return ret; 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci csi->source = source; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci return 0; 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 45162306a36Sopenharmony_ci * Registration 45262306a36Sopenharmony_ci */ 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic const struct media_entity_operations rkisp1_csi_media_ops = { 45562306a36Sopenharmony_ci .link_validate = v4l2_subdev_link_validate, 45662306a36Sopenharmony_ci}; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic const struct v4l2_subdev_video_ops rkisp1_csi_video_ops = { 45962306a36Sopenharmony_ci .s_stream = rkisp1_csi_s_stream, 46062306a36Sopenharmony_ci}; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_cistatic const struct v4l2_subdev_pad_ops rkisp1_csi_pad_ops = { 46362306a36Sopenharmony_ci .enum_mbus_code = rkisp1_csi_enum_mbus_code, 46462306a36Sopenharmony_ci .init_cfg = rkisp1_csi_init_config, 46562306a36Sopenharmony_ci .get_fmt = rkisp1_csi_get_fmt, 46662306a36Sopenharmony_ci .set_fmt = rkisp1_csi_set_fmt, 46762306a36Sopenharmony_ci}; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic const struct v4l2_subdev_ops rkisp1_csi_ops = { 47062306a36Sopenharmony_ci .video = &rkisp1_csi_video_ops, 47162306a36Sopenharmony_ci .pad = &rkisp1_csi_pad_ops, 47262306a36Sopenharmony_ci}; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ciint rkisp1_csi_register(struct rkisp1_device *rkisp1) 47562306a36Sopenharmony_ci{ 47662306a36Sopenharmony_ci struct rkisp1_csi *csi = &rkisp1->csi; 47762306a36Sopenharmony_ci struct v4l2_subdev_state state = {}; 47862306a36Sopenharmony_ci struct media_pad *pads; 47962306a36Sopenharmony_ci struct v4l2_subdev *sd; 48062306a36Sopenharmony_ci int ret; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci csi->rkisp1 = rkisp1; 48362306a36Sopenharmony_ci mutex_init(&csi->lock); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci sd = &csi->sd; 48662306a36Sopenharmony_ci v4l2_subdev_init(sd, &rkisp1_csi_ops); 48762306a36Sopenharmony_ci sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; 48862306a36Sopenharmony_ci sd->entity.ops = &rkisp1_csi_media_ops; 48962306a36Sopenharmony_ci sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; 49062306a36Sopenharmony_ci sd->owner = THIS_MODULE; 49162306a36Sopenharmony_ci strscpy(sd->name, RKISP1_CSI_DEV_NAME, sizeof(sd->name)); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci pads = csi->pads; 49462306a36Sopenharmony_ci pads[RKISP1_CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK | 49562306a36Sopenharmony_ci MEDIA_PAD_FL_MUST_CONNECT; 49662306a36Sopenharmony_ci pads[RKISP1_CSI_PAD_SRC].flags = MEDIA_PAD_FL_SOURCE | 49762306a36Sopenharmony_ci MEDIA_PAD_FL_MUST_CONNECT; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci csi->sink_fmt = rkisp1_mbus_info_get_by_code(RKISP1_CSI_DEF_FMT); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci ret = media_entity_pads_init(&sd->entity, RKISP1_CSI_PAD_NUM, pads); 50262306a36Sopenharmony_ci if (ret) 50362306a36Sopenharmony_ci goto error; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci state.pads = csi->pad_cfg; 50662306a36Sopenharmony_ci rkisp1_csi_init_config(sd, &state); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci ret = v4l2_device_register_subdev(&csi->rkisp1->v4l2_dev, sd); 50962306a36Sopenharmony_ci if (ret) { 51062306a36Sopenharmony_ci dev_err(sd->dev, "Failed to register csi receiver subdev\n"); 51162306a36Sopenharmony_ci goto error; 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci return 0; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_cierror: 51762306a36Sopenharmony_ci media_entity_cleanup(&sd->entity); 51862306a36Sopenharmony_ci mutex_destroy(&csi->lock); 51962306a36Sopenharmony_ci csi->rkisp1 = NULL; 52062306a36Sopenharmony_ci return ret; 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_civoid rkisp1_csi_unregister(struct rkisp1_device *rkisp1) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci struct rkisp1_csi *csi = &rkisp1->csi; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci if (!csi->rkisp1) 52862306a36Sopenharmony_ci return; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci v4l2_device_unregister_subdev(&csi->sd); 53162306a36Sopenharmony_ci media_entity_cleanup(&csi->sd.entity); 53262306a36Sopenharmony_ci mutex_destroy(&csi->lock); 53362306a36Sopenharmony_ci} 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ciint rkisp1_csi_init(struct rkisp1_device *rkisp1) 53662306a36Sopenharmony_ci{ 53762306a36Sopenharmony_ci struct rkisp1_csi *csi = &rkisp1->csi; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci csi->rkisp1 = rkisp1; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci csi->dphy = devm_phy_get(rkisp1->dev, "dphy"); 54262306a36Sopenharmony_ci if (IS_ERR(csi->dphy)) 54362306a36Sopenharmony_ci return dev_err_probe(rkisp1->dev, PTR_ERR(csi->dphy), 54462306a36Sopenharmony_ci "Couldn't get the MIPI D-PHY\n"); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci phy_init(csi->dphy); 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci return 0; 54962306a36Sopenharmony_ci} 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_civoid rkisp1_csi_cleanup(struct rkisp1_device *rkisp1) 55262306a36Sopenharmony_ci{ 55362306a36Sopenharmony_ci struct rkisp1_csi *csi = &rkisp1->csi; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci phy_exit(csi->dphy); 55662306a36Sopenharmony_ci} 557