diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-09-01 10:34:52 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-09-01 10:34:52 -0700 |
commit | 835d31d319d9c8c4eb6cac074643360ba0ecab10 (patch) | |
tree | 824dc6286c3f34357de0a0c12d0311eca9a6da8d /drivers/staging | |
parent | 0d290223a6c77107b1c3988959e49279a8dafaba (diff) | |
parent | 9c3a0f285248899dfa81585bc5d5bc9ebdb8fead (diff) |
Merge tag 'media/v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab:
- new sensor drivers: imx335, imx412, ov9282
- new IR transmitter driver: meson-ir-tx
- handro driver gained support for H.264 for Rockchip VDPU2
- imx gained support for i.MX8MQ
- ti-vpe has gained support for other SoC variants
- lots of cleanups, fixes, board additions and doc improvements
* tag 'media/v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (195 commits)
media: venus: venc: add support for V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM control
media: venus: venc: Add support for intra-refresh period
media: v4l2-ctrls: Add intra-refresh period control
media: docs: ext-ctrls-codec: Document cyclic intra-refresh zero control value
media: venus: helper: do not set constrained parameters for UBWC
media: venus: venc: Fix potential null pointer dereference on pointer fmt
media: venus: hfi: fix return value check in sys_get_prop_image_version()
media: tegra-cec: Handle errors of clk_prepare_enable()
media: cec-pin: rename timer overrun variables
media: TDA1997x: report -ENOLINK after disconnecting HDMI source
media: TDA1997x: fix tda1997x_query_dv_timings() return value
media: Fix cosmetic error in TDA1997x driver
media: v4l2-dv-timings.c: fix wrong condition in two for-loops
media: imx: add a driver for i.MX8MQ mipi csi rx phy and controller
media: dt-bindings: media: document the nxp,imx8mq-mipi-csi2 receiver phy and controller
media: imx: imx7_mipi_csis: convert some switch cases to the default
media: imx: imx7-media-csi: Fix buffer return upon stream start failure
media: imx: imx7-media-csi: Don't set PIXEL_BIT in CSICR1
media: imx: imx7-media-csi: Set TWO_8BIT_SENSOR for >= 10-bit formats
media: dt-bindings: media: nxp,imx7-csi: Add i.MX8MM support
...
Diffstat (limited to 'drivers/staging')
41 files changed, 1883 insertions, 503 deletions
diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c index 9363c1a52ae9..4d769590f2d3 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c @@ -849,21 +849,14 @@ static int gc2235_get_fmt(struct v4l2_subdev *sd, static int gc2235_detect(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - u16 high, low; - int ret; + u16 high = 0, low = 0; u16 id; if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) return -ENODEV; - ret = gc2235_read_reg(client, GC2235_8BIT, - GC2235_SENSOR_ID_H, &high); - if (ret) { - dev_err(&client->dev, "sensor_id_high = 0x%x\n", high); - return -ENODEV; - } - ret = gc2235_read_reg(client, GC2235_8BIT, - GC2235_SENSOR_ID_L, &low); + gc2235_read_reg(client, GC2235_8BIT, GC2235_SENSOR_ID_H, &high); + gc2235_read_reg(client, GC2235_8BIT, GC2235_SENSOR_ID_L, &low); id = ((high << 8) | low); if (id != GC2235_ID) { diff --git a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c index 11196180a206..49f4090856d3 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-mt9m114.c @@ -570,14 +570,13 @@ static int power_down(struct v4l2_subdev *sd) static int mt9m114_s_power(struct v4l2_subdev *sd, int power) { - if (power == 0) { + if (power == 0) return power_down(sd); - } else { - if (power_up(sd)) - return -EINVAL; - return mt9m114_init_common(sd); - } + if (power_up(sd)) + return -EINVAL; + + return mt9m114_init_common(sd); } /* @@ -1545,16 +1544,19 @@ static struct v4l2_ctrl_config mt9m114_controls[] = { static int mt9m114_detect(struct mt9m114_device *dev, struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - u32 retvalue; + u32 model; + int ret; if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "%s: i2c error", __func__); return -ENODEV; } - mt9m114_read_reg(client, MISENSOR_16BIT, (u32)MT9M114_PID, &retvalue); - dev->real_model_id = retvalue; + ret = mt9m114_read_reg(client, MISENSOR_16BIT, MT9M114_PID, &model); + if (ret) + return ret; + dev->real_model_id = model; - if (retvalue != MT9M114_MOD_ID) { + if (model != MT9M114_MOD_ID) { dev_err(&client->dev, "%s: failed: client->addr = %x\n", __func__, client->addr); return -ENODEV; diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index 4d43b45915e5..874115f35fca 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -627,7 +627,7 @@ static struct ov2680_reg const ov2680_1296x976_30fps[] = { {0x5706, 0x0c}, {0x5707, 0x78}, {0x3820, 0xc0}, - {0x3821, 0x00}, //miror/flip + {0x3821, 0x00}, //mirror/flip // {0x5090, 0x0c}, {} }; diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c index 0828ca9ab6f2..5e3670c4fc29 100644 --- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c +++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c @@ -932,7 +932,7 @@ err: static int ad5823_t_focus_vcm(struct v4l2_subdev *sd, u16 val) { struct i2c_client *client = v4l2_get_subdevdata(sd); - int ret = -EINVAL; + int ret; u8 vcm_code; ret = ad5823_i2c_read(client, AD5823_REG_VCM_CODE_MSB, &vcm_code); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h index a60551450c45..c16eaf3d126f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h @@ -83,8 +83,6 @@ int atomisp_q_dis_buffer_to_css(struct atomisp_sub_device *asd, void ia_css_mmu_invalidate_cache(void); -void ia_css_mmu_invalidate_cache(void); - int atomisp_css_start(struct atomisp_sub_device *asd, enum ia_css_pipe_id pipe_id, bool in_reset); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index f60198bb8a1a..99a632f33d2d 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -2102,9 +2102,6 @@ void atomisp_css_stop(struct atomisp_sub_device *asd, enum ia_css_pipe_id pipe_id, bool in_reset) { struct atomisp_device *isp = asd->isp; - struct atomisp_s3a_buf *s3a_buf; - struct atomisp_dis_buf *dis_buf; - struct atomisp_metadata_buf *md_buf; unsigned long irqflags; unsigned int i; @@ -2144,42 +2141,17 @@ void atomisp_css_stop(struct atomisp_sub_device *asd, } /* move stats buffers to free queue list */ - while (!list_empty(&asd->s3a_stats_in_css)) { - s3a_buf = list_entry(asd->s3a_stats_in_css.next, - struct atomisp_s3a_buf, list); - list_del(&s3a_buf->list); - list_add_tail(&s3a_buf->list, &asd->s3a_stats); - } - while (!list_empty(&asd->s3a_stats_ready)) { - s3a_buf = list_entry(asd->s3a_stats_ready.next, - struct atomisp_s3a_buf, list); - list_del(&s3a_buf->list); - list_add_tail(&s3a_buf->list, &asd->s3a_stats); - } + list_splice_init(&asd->s3a_stats_in_css, &asd->s3a_stats); + list_splice_init(&asd->s3a_stats_ready, &asd->s3a_stats); spin_lock_irqsave(&asd->dis_stats_lock, irqflags); - while (!list_empty(&asd->dis_stats_in_css)) { - dis_buf = list_entry(asd->dis_stats_in_css.next, - struct atomisp_dis_buf, list); - list_del(&dis_buf->list); - list_add_tail(&dis_buf->list, &asd->dis_stats); - } + list_splice_init(&asd->dis_stats_in_css, &asd->dis_stats); asd->params.dis_proj_data_valid = false; spin_unlock_irqrestore(&asd->dis_stats_lock, irqflags); for (i = 0; i < ATOMISP_METADATA_TYPE_NUM; i++) { - while (!list_empty(&asd->metadata_in_css[i])) { - md_buf = list_entry(asd->metadata_in_css[i].next, - struct atomisp_metadata_buf, list); - list_del(&md_buf->list); - list_add_tail(&md_buf->list, &asd->metadata[i]); - } - while (!list_empty(&asd->metadata_ready[i])) { - md_buf = list_entry(asd->metadata_ready[i].next, - struct atomisp_metadata_buf, list); - list_del(&md_buf->list); - list_add_tail(&md_buf->list, &asd->metadata[i]); - } + list_splice_init(&asd->metadata_in_css[i], &asd->metadata[i]); + list_splice_init(&asd->metadata_ready[i], &asd->metadata[i]); } atomisp_flush_params_queue(&asd->video_out_capture); diff --git a/drivers/staging/media/atomisp/pci/atomisp_csi2.c b/drivers/staging/media/atomisp/pci/atomisp_csi2.c index 56456e59bf89..11b6b1216473 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_csi2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_csi2.c @@ -28,7 +28,8 @@ static struct v4l2_mbus_framefmt *__csi2_get_format(struct struct v4l2_subdev_state *sd_state, enum v4l2_subdev_format_whence - which, unsigned int pad) { + which, unsigned int pad) +{ if (which == V4L2_SUBDEV_FORMAT_TRY) return v4l2_subdev_get_try_format(&csi2->subdev, sd_state, pad); diff --git a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c index f670faf978e6..dcb571f515a7 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c +++ b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c @@ -96,7 +96,7 @@ opt_err: static ssize_t iunit_dbglvl_show(struct device_driver *drv, char *buf) { iunit_debug.dbglvl = dbg_level; - return sprintf(buf, "dtrace level:%u\n", iunit_debug.dbglvl); + return sysfs_emit(buf, "dtrace level:%u\n", iunit_debug.dbglvl); } static ssize_t iunit_dbglvl_store(struct device_driver *drv, const char *buf, @@ -115,7 +115,7 @@ static ssize_t iunit_dbglvl_store(struct device_driver *drv, const char *buf, static ssize_t iunit_dbgfun_show(struct device_driver *drv, char *buf) { iunit_debug.dbgfun = atomisp_get_css_dbgfunc(); - return sprintf(buf, "dbgfun opt:%u\n", iunit_debug.dbgfun); + return sysfs_emit(buf, "dbgfun opt:%u\n", iunit_debug.dbgfun); } static ssize_t iunit_dbgfun_store(struct device_driver *drv, const char *buf, @@ -139,7 +139,7 @@ static ssize_t iunit_dbgfun_store(struct device_driver *drv, const char *buf, static ssize_t iunit_dbgopt_show(struct device_driver *drv, char *buf) { - return sprintf(buf, "option:0x%x\n", iunit_debug.dbgopt); + return sysfs_emit(buf, "option:0x%x\n", iunit_debug.dbgopt); } static ssize_t iunit_dbgopt_store(struct device_driver *drv, const char *buf, diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index 135994d44802..d8c9e31314b2 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -1040,10 +1040,10 @@ static struct camera_sensor_platform_data acpi_gmin_plat = { .get_vcm_ctrl = gmin_get_vcm_ctrl, }; -struct camera_sensor_platform_data *gmin_camera_platform_data( - struct v4l2_subdev *subdev, - enum atomisp_input_format csi_format, - enum atomisp_bayer_order csi_bayer) +struct camera_sensor_platform_data * +gmin_camera_platform_data(struct v4l2_subdev *subdev, + enum atomisp_input_format csi_format, + enum atomisp_bayer_order csi_bayer) { u8 pmic_i2c_addr = gmin_detect_pmic(subdev); struct gmin_subdev *gs; diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index 948769ca6539..1e324f1f656e 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -1763,7 +1763,8 @@ static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i if (err < 0) goto register_entities_fail; /* init atomisp wdts */ - if (init_atomisp_wdts(isp) != 0) + err = init_atomisp_wdts(isp); + if (err != 0) goto wdt_work_queue_fail; /* save the iunit context only once after all the values are init'ed. */ @@ -1815,6 +1816,7 @@ request_irq_fail: hmm_cleanup(); hmm_pool_unregister(HMM_POOL_TYPE_RESERVED); hmm_pool_fail: + pm_runtime_get_noresume(&pdev->dev); destroy_workqueue(isp->wdt_work_queue); wdt_work_queue_fail: atomisp_acc_cleanup(isp); diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c b/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c index 0f5a231672a8..8e085dda0c18 100644 --- a/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c +++ b/drivers/staging/media/atomisp/pci/hive_isp_css_common/host/input_system.c @@ -174,8 +174,6 @@ void input_system_get_state( ctrl_unit_get_state(ID, sub_id, &state->ctrl_unit_state[sub_id - CTRL_UNIT0_ID]); } - - return; } void receiver_get_state( @@ -246,8 +244,6 @@ void receiver_get_state( _HRT_CSS_RECEIVER_BE_IRQ_STATUS_REG_IDX); state->be_irq_clear = receiver_reg_load(ID, _HRT_CSS_RECEIVER_BE_IRQ_CLEAR_REG_IDX); - - return; } bool is_mipi_format_yuv420( @@ -310,8 +306,6 @@ void receiver_set_compression( reg = ((field_id < 6) ? (val << (field_id * 5)) : (val << (( field_id - 6) * 5))); receiver_reg_store(ID, addr, reg); - - return; } void receiver_port_enable( @@ -330,7 +324,6 @@ void receiver_port_enable( receiver_port_reg_store(ID, port_ID, _HRT_CSS_RECEIVER_DEVICE_READY_REG_IDX, reg); - return; } bool is_receiver_port_enabled( @@ -349,7 +342,6 @@ void receiver_irq_enable( { receiver_port_reg_store(ID, port_ID, _HRT_CSS_RECEIVER_IRQ_ENABLE_REG_IDX, irq_info); - return; } rx_irq_info_t receiver_get_irq_info( @@ -367,7 +359,6 @@ void receiver_irq_clear( { receiver_port_reg_store(ID, port_ID, _HRT_CSS_RECEIVER_IRQ_STATUS_REG_IDX, irq_info); - return; } static inline void capture_unit_get_state( @@ -428,8 +419,6 @@ static inline void capture_unit_get_state( state->FSM_State_Info = input_system_sub_system_reg_load(ID, sub_id, CAPT_FSM_STATE_INFO_REG_ID); - - return; } static inline void acquisition_unit_get_state( @@ -478,8 +467,6 @@ static inline void acquisition_unit_get_state( state->Int_Cntr_Info = input_system_sub_system_reg_load(ID, sub_id, ACQ_INT_CNTR_INFO_REG_ID); - - return; } static inline void ctrl_unit_get_state( @@ -561,8 +548,6 @@ static inline void ctrl_unit_get_state( state->capt_reserve_one_mem_region = input_system_sub_system_reg_load(ID, sub_id, ISYS_CTRL_CAPT_RESERVE_ONE_MEM_REGION_REG_ID); - - return; } static inline void mipi_port_get_state( @@ -597,8 +582,6 @@ static inline void mipi_port_get_state( state->lane_sync_count[i] = (uint8_t)((state->sync_count) >> (i * 8)); state->lane_rx_count[i] = (uint8_t)((state->rx_count) >> (i * 8)); } - - return; } static inline void rx_channel_get_state( @@ -652,8 +635,6 @@ static inline void rx_channel_get_state( state->comp[i] = (mipi_compressor_t)(val & 0x07); state->pred[i] = (mipi_predictor_t)((val & 0x18) >> 3); } - - return; } // MW: "2400" in the name is not good, but this is to avoid a naming conflict @@ -672,8 +653,6 @@ static void receiver_rst( } // AM: Additional actions for stopping receiver? - - return; } //Single function to reset all the devices mapped via GP_DEVICE. @@ -722,8 +701,6 @@ static void gp_device_rst(const gp_device_ID_t ID) // gp_device_reg_store(ID, _REG_GP_SYNCGEN_FRAME_CNT_ADDR, ZERO); gp_device_reg_store(ID, _REG_GP_SOFT_RESET_ADDR, ZERO); // AM: Maybe this soft reset is not safe. - - return; } static void input_selector_cfg_for_sensor(const gp_device_ID_t ID) @@ -740,8 +717,6 @@ static void input_selector_cfg_for_sensor(const gp_device_ID_t ID) gp_device_reg_store(ID, _REG_GP_ISEL_SBAND_SEL_ADDR, ZERO); gp_device_reg_store(ID, _REG_GP_ISEL_SYNC_SEL_ADDR, ZERO); gp_device_reg_store(ID, _REG_GP_SOFT_RESET_ADDR, ZERO); - - return; } static void input_switch_rst(const gp_device_ID_t ID) @@ -760,8 +735,6 @@ static void input_switch_rst(const gp_device_ID_t ID) gp_device_reg_store(ID, _REG_GP_IFMT_input_switch_fsync_lut, ZERO); - - return; } static void input_switch_cfg( @@ -786,8 +759,6 @@ static void input_switch_cfg( gp_device_reg_store(ID, _REG_GP_IFMT_input_switch_fsync_lut, cfg->vsync_data_reg); - - return; } static void input_system_network_rst(const input_system_ID_t ID) @@ -843,8 +814,6 @@ static void input_system_network_rst(const input_system_ID_t ID) ISYS_CTRL_INIT_REG_ID, 1U); //AM: Is there any named constant? } - - return; } // Function that resets current configuration. @@ -903,17 +872,10 @@ static input_system_err_t input_system_configure_channel( error = input_system_configure_channel_sensor(channel); break; case INPUT_SYSTEM_SOURCE_TPG: - return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; case INPUT_SYSTEM_SOURCE_PRBS: - return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; case INPUT_SYSTEM_SOURCE_FIFO: - return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; default: return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; } if (error != INPUT_SYSTEM_ERR_NO_ERROR) return error; @@ -995,7 +957,6 @@ static input_system_err_t input_buffer_configuration(void) default: config.csi_buffer_flags[port] |= INPUT_SYSTEM_CFG_FLAG_CONFLICT; return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; } // Check acquisition buffer specified but set it later since it has to be unique. @@ -1032,7 +993,6 @@ static input_system_err_t input_buffer_configuration(void) default: return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; } } else { config.csi_buffer_flags[port] = INPUT_SYSTEM_CFG_FLAG_BLOCKED; @@ -1081,8 +1041,6 @@ static void capture_unit_configure( sub_id, CAPT_NUM_MEM_REGIONS_REG_ID, cfg->nof_mem_regs); - - return; } static void acquisition_unit_configure( @@ -1106,8 +1064,6 @@ static void acquisition_unit_configure( sub_id, ACQ_MEM_REGION_SIZE_REG_ID, cfg->mem_reg_size); - - return; } static void ctrl_unit_configure( @@ -1174,7 +1130,6 @@ static void ctrl_unit_configure( sub_id, ISYS_CTRL_CAPT_RESERVE_ONE_MEM_REGION_REG_ID, 0); - return; } static void input_system_network_configure( @@ -1232,8 +1187,6 @@ static void input_system_network_configure( sub_id, &cfg->ctrl_unit_cfg[sub_id - CTRL_UNIT0_ID]); } - - return; } static input_system_err_t configuration_to_registers(void) @@ -1307,19 +1260,12 @@ static input_system_err_t configuration_to_registers(void) break; case INPUT_SYSTEM_SOURCE_TPG: - - break; - case INPUT_SYSTEM_SOURCE_PRBS: - - break; - case INPUT_SYSTEM_SOURCE_FIFO: break; default: return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; } // end of switch (source_type) @@ -1695,19 +1641,11 @@ static input_system_err_t input_system_configure_channel_sensor( break; case INPUT_SYSTEM_FIFO_CAPTURE_WITH_COUNTING: - return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; case INPUT_SYSTEM_XMEM_CAPTURE: - return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; case INPUT_SYSTEM_XMEM_ACQUIRE: - return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; default: return INPUT_SYSTEM_ERR_PARAMETER_NOT_SUPPORTED; - break; } - return INPUT_SYSTEM_ERR_NO_ERROR; } // Test flags and set structure. diff --git a/drivers/staging/media/atomisp/pci/input_system_ctrl_defs.h b/drivers/staging/media/atomisp/pci/input_system_ctrl_defs.h index c801ddd71192..b2076a96987c 100644 --- a/drivers/staging/media/atomisp/pci/input_system_ctrl_defs.h +++ b/drivers/staging/media/atomisp/pci/input_system_ctrl_defs.h @@ -27,7 +27,7 @@ // Number of registers #define ISYS_CTRL_NOF_REGS 23 -// Register id's of MMIO slave accesible registers +// Register id's of MMIO slave accessible registers #define ISYS_CTRL_CAPT_START_ADDR_A_REG_ID 0 #define ISYS_CTRL_CAPT_START_ADDR_B_REG_ID 1 #define ISYS_CTRL_CAPT_START_ADDR_C_REG_ID 2 diff --git a/drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_types.h b/drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_types.h index be3534e46c15..9b22f2da45d5 100644 --- a/drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_types.h +++ b/drivers/staging/media/atomisp/pci/isp/kernels/anr/anr_1.0/ia_css_anr_types.h @@ -17,8 +17,8 @@ #define __IA_CSS_ANR_TYPES_H /* @file -* CSS-API header file for Advanced Noise Reduction kernel v1 -*/ + * CSS-API header file for Advanced Noise Reduction kernel v1 + */ /* Application specific DMA settings */ #define ANR_BPP 10 diff --git a/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h b/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h index 072a92199e05..2614b89b8e34 100644 --- a/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h +++ b/drivers/staging/media/atomisp/pci/isp2400_input_system_local.h @@ -356,41 +356,13 @@ struct rx_cfg_s { }; /* NOTE: The base has already an offset of 0x0100 */ -static const hrt_address MIPI_PORT_OFFSET[N_MIPI_PORT_ID] = { +static const hrt_address __maybe_unused MIPI_PORT_OFFSET[N_MIPI_PORT_ID] = { 0x00000000UL, 0x00000100UL, 0x00000200UL }; -static const mipi_lane_cfg_t MIPI_PORT_MAXLANES[N_MIPI_PORT_ID] = { - MIPI_4LANE_CFG, - MIPI_1LANE_CFG, - MIPI_2LANE_CFG -}; - -static const bool MIPI_PORT_ACTIVE[N_RX_MODE][N_MIPI_PORT_ID] = { - {true, true, false}, - {true, true, false}, - {true, true, false}, - {true, true, false}, - {true, true, true}, - {true, true, true}, - {true, true, true}, - {true, true, true} -}; - -static const mipi_lane_cfg_t MIPI_PORT_LANES[N_RX_MODE][N_MIPI_PORT_ID] = { - {MIPI_4LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG}, - {MIPI_3LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG}, - {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG}, - {MIPI_1LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG}, - {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_2LANE_CFG}, - {MIPI_3LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG}, - {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG}, - {MIPI_1LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG} -}; - -static const hrt_address SUB_SYSTEM_OFFSET[N_SUB_SYSTEM_ID] = { +static const hrt_address __maybe_unused SUB_SYSTEM_OFFSET[N_SUB_SYSTEM_ID] = { 0x00001000UL, 0x00002000UL, 0x00003000UL, diff --git a/drivers/staging/media/atomisp/pci/isp_acquisition_defs.h b/drivers/staging/media/atomisp/pci/isp_acquisition_defs.h index 8e4bddc3790d..7e8f6f2178aa 100644 --- a/drivers/staging/media/atomisp/pci/isp_acquisition_defs.h +++ b/drivers/staging/media/atomisp/pci/isp_acquisition_defs.h @@ -35,7 +35,7 @@ #define NOF_ACQ_REGS 12 -// Register id's of MMIO slave accesible registers +// Register id's of MMIO slave accessible registers #define ACQ_START_ADDR_REG_ID 0 #define ACQ_MEM_REGION_SIZE_REG_ID 1 #define ACQ_NUM_MEM_REGIONS_REG_ID 2 diff --git a/drivers/staging/media/atomisp/pci/isp_capture_defs.h b/drivers/staging/media/atomisp/pci/isp_capture_defs.h index 14cbb6390d3e..b9e5ed932702 100644 --- a/drivers/staging/media/atomisp/pci/isp_capture_defs.h +++ b/drivers/staging/media/atomisp/pci/isp_capture_defs.h @@ -33,7 +33,7 @@ // Number of registers #define CAPT_NOF_REGS 16 -// Register id's of MMIO slave accesible registers +// Register id's of MMIO slave accessible registers #define CAPT_START_MODE_REG_ID 0 #define CAPT_START_ADDR_REG_ID 1 #define CAPT_MEM_REGION_SIZE_REG_ID 2 diff --git a/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c b/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c index 4a18da6bf0c1..af153c3fb86d 100644 --- a/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c +++ b/drivers/staging/media/atomisp/pci/runtime/isys/src/rx.c @@ -476,10 +476,20 @@ unsigned int ia_css_csi2_calculate_input_system_alignment( #endif #if !defined(ISP2401) +static const mipi_lane_cfg_t MIPI_PORT_LANES[N_RX_MODE][N_MIPI_PORT_ID] = { + {MIPI_4LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG}, + {MIPI_3LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG}, + {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG}, + {MIPI_1LANE_CFG, MIPI_1LANE_CFG, MIPI_0LANE_CFG}, + {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_2LANE_CFG}, + {MIPI_3LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG}, + {MIPI_2LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG}, + {MIPI_1LANE_CFG, MIPI_1LANE_CFG, MIPI_1LANE_CFG} +}; + void ia_css_isys_rx_configure(const rx_cfg_t *config, const enum ia_css_input_mode input_mode) { - bool port_enabled[N_MIPI_PORT_ID]; bool any_port_enabled = false; enum mipi_port_id port; @@ -516,8 +526,6 @@ void ia_css_isys_rx_configure(const rx_cfg_t *config, _HRT_CSS_RECEIVER_2400_RX_COUNT_REG_IDX, config->rxcount); - port_enabled[port] = true; - if (input_mode != IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { /* MW: A bit of a hack, straight wiring of the capture * units,assuming they are linearly enumerated. */ diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index d26b1301eeb7..c4b35cbab373 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -3224,24 +3224,22 @@ init_vf_frameinfo_defaults(struct ia_css_pipe *pipe, #ifdef ISP2401 static unsigned int -get_crop_lines_for_bayer_order( - const struct ia_css_stream_config *config) +get_crop_lines_for_bayer_order(const struct ia_css_stream_config *config) { assert(config); - if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR) - || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG)) + if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_BGGR) || + (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG)) return 1; return 0; } static unsigned int -get_crop_columns_for_bayer_order( - const struct ia_css_stream_config *config) +get_crop_columns_for_bayer_order(const struct ia_css_stream_config *config) { assert(config); - if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB) - || (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG)) + if ((config->input_config.bayer_order == IA_CSS_BAYER_ORDER_RGGB) || + (config->input_config.bayer_order == IA_CSS_BAYER_ORDER_GBRG)) return 1; return 0; @@ -5170,7 +5168,7 @@ sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe, if (binary) { err = ia_css_binary_3a_grid_info(binary, info, pipe); if (err) - goto ERR; + goto err; } else { memset(&info->s3a_grid, 0, sizeof(info->s3a_grid)); } @@ -5181,10 +5179,7 @@ sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe, ia_css_binary_dvs_grid_info(binary, info, pipe); ia_css_binary_dvs_stat_grid_info(binary, info, pipe); } else { - memset(&info->dvs_grid.dvs_grid_info, 0, - sizeof(info->dvs_grid.dvs_grid_info)); - memset(&info->dvs_grid.dvs_stat_grid_info, 0, - sizeof(info->dvs_grid.dvs_stat_grid_info)); + memset(&info->dvs_grid, 0, sizeof(info->dvs_grid)); } if (binary) { @@ -5195,7 +5190,7 @@ sh_css_pipe_get_grid_info(struct ia_css_pipe *pipe, info->vamem_type = IA_CSS_VAMEM_TYPE_2; -ERR : +err: IA_CSS_LEAVE_ERR_PRIVATE(err); return err; } @@ -5328,14 +5323,15 @@ static int load_video_binaries(struct ia_css_pipe *pipe) if (err) return err; mycs->num_yuv_scaler = cas_scaler_descr.num_stage; - mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * - sizeof(struct ia_css_binary), GFP_KERNEL); + mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage, + sizeof(struct ia_css_binary), + GFP_KERNEL); if (!mycs->yuv_scaler_binary) { err = -ENOMEM; return err; } - mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage - * sizeof(bool), GFP_KERNEL); + mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage, + sizeof(bool), GFP_KERNEL); if (!mycs->is_output_stage) { err = -ENOMEM; return err; @@ -5938,14 +5934,15 @@ static int load_primary_binaries( return err; } mycs->num_yuv_scaler = cas_scaler_descr.num_stage; - mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * - sizeof(struct ia_css_binary), GFP_KERNEL); + mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage, + sizeof(struct ia_css_binary), + GFP_KERNEL); if (!mycs->yuv_scaler_binary) { err = -ENOMEM; IA_CSS_LEAVE_ERR_PRIVATE(err); return err; } - mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage * + mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage, sizeof(bool), GFP_KERNEL); if (!mycs->is_output_stage) { err = -ENOMEM; @@ -6989,14 +6986,14 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) goto ERR; mycs->num_output = cas_scaler_descr.num_output_stage; mycs->num_yuv_scaler = cas_scaler_descr.num_stage; - mycs->yuv_scaler_binary = kzalloc(cas_scaler_descr.num_stage * + mycs->yuv_scaler_binary = kcalloc(cas_scaler_descr.num_stage, sizeof(struct ia_css_binary), GFP_KERNEL); if (!mycs->yuv_scaler_binary) { err = -ENOMEM; goto ERR; } - mycs->is_output_stage = kzalloc(cas_scaler_descr.num_stage * + mycs->is_output_stage = kcalloc(cas_scaler_descr.num_stage, sizeof(bool), GFP_KERNEL); if (!mycs->is_output_stage) { err = -ENOMEM; @@ -7097,7 +7094,7 @@ load_yuvpp_binaries(struct ia_css_pipe *pipe) mycs->num_vf_pp = 1; } - mycs->vf_pp_binary = kzalloc(mycs->num_vf_pp * + mycs->vf_pp_binary = kcalloc(mycs->num_vf_pp, sizeof(struct ia_css_binary), GFP_KERNEL); if (!mycs->vf_pp_binary) { @@ -10162,7 +10159,7 @@ ia_css_stop_sp(void) timeout--; udelay(1); } - if ((ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED)) + if (ia_css_spctrl_get_state(SP0_ID) != IA_CSS_SP_SW_TERMINATED) IA_CSS_WARNING("SP has not terminated (SW)"); if (timeout == 0) { diff --git a/drivers/staging/media/atomisp/pci/sh_css_firmware.c b/drivers/staging/media/atomisp/pci/sh_css_firmware.c index f4ce8ace9d50..e1a16a50e588 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_firmware.c +++ b/drivers/staging/media/atomisp/pci/sh_css_firmware.c @@ -363,10 +363,8 @@ void sh_css_unload_firmware(void) unsigned int i = 0; for (i = 0; i < sh_css_num_binaries; i++) { - if (fw_minibuffer[i].name) - kfree((void *)fw_minibuffer[i].name); - if (fw_minibuffer[i].buffer) - kvfree(fw_minibuffer[i].buffer); + kfree(fw_minibuffer[i].name); + kvfree(fw_minibuffer[i].buffer); } kfree(fw_minibuffer); fw_minibuffer = NULL; diff --git a/drivers/staging/media/atomisp/pci/sh_css_mipi.c b/drivers/staging/media/atomisp/pci/sh_css_mipi.c index 3f34cc81be87..75489f7d75ee 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_mipi.c +++ b/drivers/staging/media/atomisp/pci/sh_css_mipi.c @@ -91,7 +91,8 @@ ia_css_mipi_frame_calculate_size(const unsigned int width, const enum atomisp_input_format format, const bool hasSOLandEOL, const unsigned int embedded_data_size_words, - unsigned int *size_mem_words) { + unsigned int *size_mem_words) +{ int err = 0; unsigned int bits_per_pixel = 0; @@ -118,8 +119,7 @@ ia_css_mipi_frame_calculate_size(const unsigned int width, IA_CSS_ENTER("padded_width=%d, height=%d, format=%d, hasSOLandEOL=%d, embedded_data_size_words=%d\n", width_padded, height, format, hasSOLandEOL, embedded_data_size_words); - switch (format) - { + switch (format) { case ATOMISP_INPUT_FORMAT_RAW_6: /* 4p, 3B, 24bits */ bits_per_pixel = 6; break; @@ -178,12 +178,10 @@ ia_css_mipi_frame_calculate_size(const unsigned int width, /* Even lines for YUV420 formats are double in bits_per_pixel. */ if (format == ATOMISP_INPUT_FORMAT_YUV420_8 || format == ATOMISP_INPUT_FORMAT_YUV420_10 - || format == ATOMISP_INPUT_FORMAT_YUV420_16) - { + || format == ATOMISP_INPUT_FORMAT_YUV420_16) { even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */ - } else - { + } else { even_line_bytes = odd_line_bytes; } @@ -236,7 +234,8 @@ ia_css_mipi_frame_calculate_size(const unsigned int width, #if !defined(ISP2401) int ia_css_mipi_frame_enable_check_on_size(const enum mipi_port_id port, - const unsigned int size_mem_words) { + const unsigned int size_mem_words) +{ u32 idx; int err = -EBUSY; @@ -246,11 +245,9 @@ ia_css_mipi_frame_enable_check_on_size(const enum mipi_port_id port, for (idx = 0; idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT && my_css.mipi_sizes_for_check[port][idx] != 0; - idx++) /* do nothing */ - { + idx++) { /* do nothing */ } - if (idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT) - { + if (idx < IA_CSS_MIPI_SIZE_CHECK_MAX_NOF_ENTRIES_PER_PORT) { my_css.mipi_sizes_for_check[port][idx] = size_mem_words; err = 0; } @@ -271,7 +268,8 @@ mipi_init(void) int calculate_mipi_buff_size( struct ia_css_stream_config *stream_cfg, - unsigned int *size_mem_words) { + unsigned int *size_mem_words) +{ #if !defined(ISP2401) int err = -EINVAL; (void)stream_cfg; @@ -346,12 +344,10 @@ calculate_mipi_buff_size( /* Even lines for YUV420 formats are double in bits_per_pixel. */ if (format == ATOMISP_INPUT_FORMAT_YUV420_8 - || format == ATOMISP_INPUT_FORMAT_YUV420_10) - { + || format == ATOMISP_INPUT_FORMAT_YUV420_10) { even_line_bytes = (width_padded * 2 * bits_per_pixel + 7) >> 3; /* ceil ( bits per line / 8) */ - } else - { + } else { even_line_bytes = odd_line_bytes; } @@ -393,7 +389,8 @@ static bool buffers_needed(struct ia_css_pipe *pipe) int allocate_mipi_frames(struct ia_css_pipe *pipe, - struct ia_css_stream_info *info) { + struct ia_css_stream_info *info) +{ int err = -EINVAL; unsigned int port; @@ -402,8 +399,7 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, assert(pipe); assert(pipe->stream); - if ((!pipe) || (!pipe->stream)) - { + if ((!pipe) || (!pipe->stream)) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: pipe or stream is null.\n", pipe); @@ -411,8 +407,7 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, } #ifdef ISP2401 - if (pipe->stream->config.online) - { + if (pipe->stream->config.online) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: no buffers needed for 2401 pipe mode.\n", pipe); @@ -449,8 +444,7 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, #endif #if !defined(ISP2401) - if (ref_count_mipi_allocation[port] != 0) - { + if (ref_count_mipi_allocation[port] != 0) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) exit: already allocated for this port (port=%d).\n", pipe, port); @@ -462,8 +456,7 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, * TODO AM: Once that is changed (removed) this code should be removed as well. * In that case only 2400 related code should remain. */ - if (ref_count_mipi_allocation[port] != 0) - { + if (ref_count_mipi_allocation[port] != 0) { ref_count_mipi_allocation[port]++; ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, "allocate_mipi_frames(%p) leave: nothing to do, already allocated for this port (port=%d).\n", @@ -481,8 +474,7 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, { /* limit the scope of i,j */ unsigned int i, j; - for (i = 0; i < my_css.num_mipi_frames[port]; i++) - { + for (i = 0; i < my_css.num_mipi_frames[port]; i++) { /* free previous frame */ if (my_css.mipi_frames[port][i]) { ia_css_frame_free(my_css.mipi_frames[port][i]); @@ -535,7 +527,8 @@ allocate_mipi_frames(struct ia_css_pipe *pipe, } int -free_mipi_frames(struct ia_css_pipe *pipe) { +free_mipi_frames(struct ia_css_pipe *pipe) +{ int err = -EINVAL; unsigned int port; @@ -543,8 +536,7 @@ free_mipi_frames(struct ia_css_pipe *pipe) { "free_mipi_frames(%p) enter:\n", pipe); /* assert(pipe != NULL); TEMP: TODO: Should be assert only. */ - if (pipe) - { + if (pipe) { assert(pipe->stream); if ((!pipe) || (!pipe->stream)) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE_PRIVATE, @@ -620,8 +612,7 @@ free_mipi_frames(struct ia_css_pipe *pipe) { } #endif } - } else /* pipe ==NULL */ - { + } else { /* pipe ==NULL */ /* AM TEMP: free-ing all mipi buffers just like a legacy code. */ for (port = CSI_PORT0_ID; port < N_CSI_PORTS; port++) { unsigned int i; @@ -645,7 +636,8 @@ free_mipi_frames(struct ia_css_pipe *pipe) { } int -send_mipi_frames(struct ia_css_pipe *pipe) { +send_mipi_frames(struct ia_css_pipe *pipe) +{ int err = -EINVAL; unsigned int i; #ifndef ISP2401 @@ -658,8 +650,7 @@ send_mipi_frames(struct ia_css_pipe *pipe) { assert(pipe); assert(pipe->stream); - if (!pipe || !pipe->stream) - { + if (!pipe || !pipe->stream) { IA_CSS_ERROR("pipe or stream is null"); return -EINVAL; } @@ -686,8 +677,7 @@ send_mipi_frames(struct ia_css_pipe *pipe) { } /* Hand-over the SP-internal mipi buffers */ - for (i = 0; i < my_css.num_mipi_frames[port]; i++) - { + for (i = 0; i < my_css.num_mipi_frames[port]; i++) { /* Need to include the ofset for port. */ sh_css_update_host2sp_mipi_frame(port * NUM_MIPI_FRAMES_PER_STREAM + i, my_css.mipi_frames[port][i]); @@ -700,8 +690,7 @@ send_mipi_frames(struct ia_css_pipe *pipe) { * Send an event to inform the SP * that all MIPI frames are passed. **********************************/ - if (!sh_css_sp_is_running()) - { + if (!sh_css_sp_is_running()) { /* SP is not running. The queues are not valid */ IA_CSS_ERROR("sp is not running"); return err; diff --git a/drivers/staging/media/atomisp/pci/sh_css_params.c b/drivers/staging/media/atomisp/pci/sh_css_params.c index 644e14575987..dbd3bfe3d343 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_params.c +++ b/drivers/staging/media/atomisp/pci/sh_css_params.c @@ -813,15 +813,15 @@ convert_allocate_fpntbl(struct ia_css_isp_parameters *params) } static int -store_fpntbl(struct ia_css_isp_parameters *params, ia_css_ptr ptr) { +store_fpntbl(struct ia_css_isp_parameters *params, ia_css_ptr ptr) +{ struct ia_css_host_data *isp_data; assert(params); assert(ptr != mmgr_NULL); isp_data = convert_allocate_fpntbl(params); - if (!isp_data) - { + if (!isp_data) { IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM); return -ENOMEM; } @@ -894,7 +894,8 @@ ia_css_process_kernel(struct ia_css_stream *stream, static int sh_css_select_dp_10bpp_config(const struct ia_css_pipe *pipe, - bool *is_dp_10bpp) { + bool *is_dp_10bpp) +{ int err = 0; /* Currently we check if 10bpp DPC configuration is required based * on the use case,i.e. if BDS and DPC is both enabled. The more cleaner @@ -903,12 +904,10 @@ sh_css_select_dp_10bpp_config(const struct ia_css_pipe *pipe, * implementation. (This is because the configuration is set before a * binary is selected, and the binary info is not available) */ - if ((!pipe) || (!is_dp_10bpp)) - { + if ((!pipe) || (!is_dp_10bpp)) { IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); err = -EINVAL; - } else - { + } else { *is_dp_10bpp = false; /* check if DPC is enabled from the host */ @@ -936,7 +935,8 @@ sh_css_select_dp_10bpp_config(const struct ia_css_pipe *pipe, int sh_css_set_black_frame(struct ia_css_stream *stream, - const struct ia_css_frame *raw_black_frame) { + const struct ia_css_frame *raw_black_frame) +{ struct ia_css_isp_parameters *params; /* this function desperately needs to be moved to the ISP or SP such * that it can use the DMA. @@ -957,13 +957,11 @@ sh_css_set_black_frame(struct ia_css_stream *stream, IA_CSS_ENTER_PRIVATE("black_frame=%p", raw_black_frame); if (params->fpn_config.data && - (params->fpn_config.width != width || params->fpn_config.height != height)) - { + (params->fpn_config.width != width || params->fpn_config.height != height)) { kvfree(params->fpn_config.data); params->fpn_config.data = NULL; } - if (!params->fpn_config.data) - { + if (!params->fpn_config.data) { params->fpn_config.data = kvmalloc(height * width * sizeof(short), GFP_KERNEL); if (!params->fpn_config.data) { @@ -977,8 +975,7 @@ sh_css_set_black_frame(struct ia_css_stream *stream, } /* store raw to fpntbl */ - for (y = 0; y < height; y++) - { + for (y = 0; y < height; y++) { for (x = 0; x < width; x += (ISP_VEC_NELEMS * 2)) { int ofs = y * width + x; @@ -1181,7 +1178,8 @@ sh_css_enable_pipeline(const struct ia_css_binary *binary) static int ia_css_process_zoom_and_motion( struct ia_css_isp_parameters *params, - const struct ia_css_pipeline_stage *first_stage) { + const struct ia_css_pipeline_stage *first_stage) +{ /* first_stage can be NULL */ const struct ia_css_pipeline_stage *stage; int err = 0; @@ -1195,8 +1193,7 @@ ia_css_process_zoom_and_motion( IA_CSS_ENTER_PRIVATE(""); /* Go through all stages to udate uds and cropping */ - for (stage = first_stage; stage; stage = stage->next) - { + for (stage = first_stage; stage; stage = stage->next) { struct ia_css_binary *binary; /* note: the var below is made static as it is quite large; if it is not static it ends up on the stack which could @@ -1581,7 +1578,8 @@ err: int ia_css_get_3a_statistics(struct ia_css_3a_statistics *host_stats, - const struct ia_css_isp_3a_statistics *isp_stats) { + const struct ia_css_isp_3a_statistics *isp_stats) +{ struct ia_css_isp_3a_statistics_map *map; int ret = 0; @@ -1591,13 +1589,11 @@ ia_css_get_3a_statistics(struct ia_css_3a_statistics *host_stats, assert(isp_stats); map = ia_css_isp_3a_statistics_map_allocate(isp_stats, NULL); - if (map) - { + if (map) { hmm_load(isp_stats->data_ptr, map->data_ptr, isp_stats->size); ia_css_translate_3a_statistics(host_stats, map); ia_css_isp_3a_statistics_map_free(map); - } else - { + } else { IA_CSS_ERROR("out of memory"); ret = -ENOMEM; } @@ -1894,7 +1890,8 @@ sh_css_pipe_isp_config_get(struct ia_css_pipe *pipe) int ia_css_stream_set_isp_config( struct ia_css_stream *stream, - const struct ia_css_isp_config *config) { + const struct ia_css_isp_config *config) +{ return ia_css_stream_set_isp_config_on_pipe(stream, config, NULL); } @@ -1902,7 +1899,8 @@ int ia_css_stream_set_isp_config_on_pipe( struct ia_css_stream *stream, const struct ia_css_isp_config *config, - struct ia_css_pipe *pipe) { + struct ia_css_pipe *pipe) +{ int err = 0; if ((!stream) || (!config)) @@ -1923,7 +1921,8 @@ ia_css_stream_set_isp_config_on_pipe( int ia_css_pipe_set_isp_config(struct ia_css_pipe *pipe, - struct ia_css_isp_config *config) { + struct ia_css_isp_config *config) +{ struct ia_css_pipe *pipe_in = pipe; int err = 0; @@ -1948,7 +1947,8 @@ static int sh_css_set_global_isp_config_on_pipe( struct ia_css_pipe *curr_pipe, const struct ia_css_isp_config *config, - struct ia_css_pipe *pipe) { + struct ia_css_pipe *pipe) +{ int err = 0; int err1 = 0; int err2 = 0; @@ -1977,7 +1977,8 @@ static int sh_css_set_per_frame_isp_config_on_pipe( struct ia_css_stream *stream, const struct ia_css_isp_config *config, - struct ia_css_pipe *pipe) { + struct ia_css_pipe *pipe) +{ unsigned int i; bool per_frame_config_created = false; int err = 0; @@ -1991,8 +1992,7 @@ sh_css_set_per_frame_isp_config_on_pipe( IA_CSS_ENTER_PRIVATE("stream=%p, config=%p, pipe=%p", stream, config, pipe); - if (!pipe) - { + if (!pipe) { err = -EINVAL; goto exit; } @@ -2000,8 +2000,7 @@ sh_css_set_per_frame_isp_config_on_pipe( /* create per-frame ISP params object with default values * from stream->isp_params_configs if one doesn't already exist */ - if (!stream->per_frame_isp_params_configs) - { + if (!stream->per_frame_isp_params_configs) { err = sh_css_create_isp_params(stream, &stream->per_frame_isp_params_configs); if (err) @@ -2012,15 +2011,13 @@ sh_css_set_per_frame_isp_config_on_pipe( params = stream->per_frame_isp_params_configs; /* update new ISP params object with the new config */ - if (!sh_css_init_isp_params_from_global(stream, params, false, pipe)) - { + if (!sh_css_init_isp_params_from_global(stream, params, false, pipe)) { err1 = -EINVAL; } err2 = sh_css_init_isp_params_from_config(stream->pipes[0], params, config, pipe); - if (per_frame_config_created) - { + if (per_frame_config_created) { ddr_ptrs = ¶ms->ddr_ptrs; ddr_ptrs_size = ¶ms->ddr_ptrs_size; /* create per pipe reference to general ddr_ptrs */ @@ -2051,7 +2048,8 @@ static int sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe, struct ia_css_isp_parameters *params, const struct ia_css_isp_config *config, - struct ia_css_pipe *pipe_in) { + struct ia_css_pipe *pipe_in) +{ int err = 0; bool is_dp_10bpp = true; @@ -2096,8 +2094,7 @@ sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe, } if (0 == - sh_css_select_dp_10bpp_config(pipe, &is_dp_10bpp)) - { + sh_css_select_dp_10bpp_config(pipe, &is_dp_10bpp)) { /* return an error when both DPC and BDS is enabled by the * user. */ /* we do not exit from this point immediately to allow internal @@ -2105,8 +2102,7 @@ sh_css_init_isp_params_from_config(struct ia_css_pipe *pipe, if (is_dp_10bpp) { err = -EINVAL; } - } else - { + } else { err = -EINVAL; goto exit; } @@ -2359,7 +2355,8 @@ static unsigned int g_param_buffer_dequeue_count; static unsigned int g_param_buffer_enqueue_count; int -ia_css_stream_isp_parameters_init(struct ia_css_stream *stream) { +ia_css_stream_isp_parameters_init(struct ia_css_stream *stream) +{ int err = 0; unsigned int i; struct sh_css_ddr_address_map *ddr_ptrs; @@ -2369,8 +2366,7 @@ ia_css_stream_isp_parameters_init(struct ia_css_stream *stream) { assert(stream); IA_CSS_ENTER_PRIVATE("void"); - if (!stream) - { + if (!stream) { IA_CSS_LEAVE_ERR_PRIVATE(-EINVAL); return -EINVAL; } @@ -2385,8 +2381,7 @@ ia_css_stream_isp_parameters_init(struct ia_css_stream *stream) { goto ERR; params = stream->isp_params_configs; - if (!sh_css_init_isp_params_from_global(stream, params, true, NULL)) - { + if (!sh_css_init_isp_params_from_global(stream, params, true, NULL)) { /* we do not return the error immediately to enable internal * firmware feature testing */ err = -EINVAL; @@ -2396,8 +2391,7 @@ ia_css_stream_isp_parameters_init(struct ia_css_stream *stream) { ddr_ptrs_size = ¶ms->ddr_ptrs_size; /* create per pipe reference to general ddr_ptrs */ - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - { + for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { ref_sh_css_ddr_address_map(ddr_ptrs, ¶ms->pipe_ddr_ptrs[i]); params->pipe_ddr_ptrs_size[i] = *ddr_ptrs_size; } @@ -2431,7 +2425,8 @@ ia_css_set_sdis2_config( static int sh_css_create_isp_params(struct ia_css_stream *stream, - struct ia_css_isp_parameters **isp_params_out) { + struct ia_css_isp_parameters **isp_params_out) +{ bool succ = true; unsigned int i; struct sh_css_ddr_address_map *ddr_ptrs; @@ -2441,23 +2436,20 @@ sh_css_create_isp_params(struct ia_css_stream *stream, struct ia_css_isp_parameters *params = kvmalloc(sizeof(struct ia_css_isp_parameters), GFP_KERNEL); - if (!params) - { + if (!params) { *isp_params_out = NULL; err = -ENOMEM; IA_CSS_ERROR("%s:%d error: cannot allocate memory", __FILE__, __LINE__); IA_CSS_LEAVE_ERR_PRIVATE(err); return err; - } else - { + } else { memset(params, 0, sizeof(struct ia_css_isp_parameters)); } ddr_ptrs = ¶ms->ddr_ptrs; ddr_ptrs_size = ¶ms->ddr_ptrs_size; - for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) - { + for (i = 0; i < IA_CSS_PIPE_ID_NUM; i++) { memset(¶ms->pipe_ddr_ptrs[i], 0, sizeof(params->pipe_ddr_ptrs[i])); memset(¶ms->pipe_ddr_ptrs_size[i], 0, @@ -2714,7 +2706,8 @@ exit: } int -sh_css_params_init(void) { +sh_css_params_init(void) +{ int i, p; IA_CSS_ENTER_PRIVATE("void"); @@ -2723,8 +2716,7 @@ sh_css_params_init(void) { g_param_buffer_dequeue_count = 0; g_param_buffer_enqueue_count = 0; - for (p = 0; p < IA_CSS_PIPE_ID_NUM; p++) - { + for (p = 0; p < IA_CSS_PIPE_ID_NUM; p++) { for (i = 0; i < SH_CSS_MAX_STAGES; i++) { xmem_sp_stage_ptrs[p][i] = ia_css_refcount_increment(-1, @@ -2762,8 +2754,7 @@ sh_css_params_init(void) { ATOMISP_MAP_FLAG_CLEARED)); if ((sp_ddr_ptrs == mmgr_NULL) || - (xmem_sp_group_ptrs == mmgr_NULL)) - { + (xmem_sp_group_ptrs == mmgr_NULL)) { ia_css_uninit(); IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM); return -ENOMEM; @@ -3094,14 +3085,14 @@ store_morph_plane( unsigned int width, unsigned int height, ia_css_ptr dest, - unsigned int aligned_width) { + unsigned int aligned_width) +{ struct ia_css_host_data *isp_data; assert(dest != mmgr_NULL); isp_data = convert_allocate_morph_plane(data, width, height, aligned_width); - if (!isp_data) - { + if (!isp_data) { IA_CSS_LEAVE_ERR_PRIVATE(-ENOMEM); return -ENOMEM; } @@ -3221,7 +3212,8 @@ int sh_css_param_update_isp_params(struct ia_css_pipe *curr_pipe, struct ia_css_isp_parameters *params, bool commit, - struct ia_css_pipe *pipe_in) { + struct ia_css_pipe *pipe_in) +{ int err = 0; ia_css_ptr cpy; int i; @@ -3238,15 +3230,13 @@ sh_css_param_update_isp_params(struct ia_css_pipe *curr_pipe, raw_bit_depth = ia_css_stream_input_format_bits_per_pixel(curr_pipe->stream); /* now make the map available to the sp */ - if (!commit) - { + if (!commit) { IA_CSS_LEAVE_ERR_PRIVATE(err); return err; } /* enqueue a copies of the mem_map to the designated pipelines */ - for (i = 0; i < curr_pipe->stream->num_pipes; i++) - { + for (i = 0; i < curr_pipe->stream->num_pipes; i++) { struct ia_css_pipe *pipe; struct sh_css_ddr_address_map *cur_map; struct sh_css_ddr_address_map_size *cur_map_size; @@ -3430,7 +3420,8 @@ sh_css_params_write_to_ddr_internal( struct ia_css_isp_parameters *params, const struct ia_css_pipeline_stage *stage, struct sh_css_ddr_address_map *ddr_map, - struct sh_css_ddr_address_map_size *ddr_map_size) { + struct sh_css_ddr_address_map_size *ddr_map_size) +{ int err; const struct ia_css_binary *binary; @@ -3452,8 +3443,7 @@ sh_css_params_write_to_ddr_internal( stage_num = stage->stage_num; - if (binary->info->sp.enable.fpnr) - { + if (binary->info->sp.enable.fpnr) { buff_realloced = reallocate_buffer(&ddr_map->fpn_tbl, &ddr_map_size->fpn_tbl, (size_t)(FPNTBL_BYTES(binary)), @@ -3474,8 +3464,7 @@ sh_css_params_write_to_ddr_internal( } } - if (binary->info->sp.enable.sc) - { + if (binary->info->sp.enable.sc) { u32 enable_conv; size_t bytes; @@ -3577,8 +3566,7 @@ sh_css_params_write_to_ddr_internal( * DPC kernel. The code below sets the pipe specific configuration to * individual binaries. */ if (IS_ISP2401 && - params->pipe_dpc_config_changed[pipe_id] && binary->info->sp.enable.dpc) - { + params->pipe_dpc_config_changed[pipe_id] && binary->info->sp.enable.dpc) { unsigned int size = stage->binary->info->mem_offsets.offsets.param->dmem.dp.size; @@ -3596,8 +3584,7 @@ sh_css_params_write_to_ddr_internal( } } - if (params->config_changed[IA_CSS_MACC_ID] && binary->info->sp.enable.macc) - { + if (params->config_changed[IA_CSS_MACC_ID] && binary->info->sp.enable.macc) { unsigned int i, j, idx; unsigned int idx_map[] = { 0, 1, 3, 2, 6, 7, 5, 4, 12, 13, 15, 14, 10, 11, 9, 8 @@ -3646,8 +3633,7 @@ sh_css_params_write_to_ddr_internal( sizeof(converted_macc_table.data)); } - if (binary->info->sp.enable.dvs_6axis) - { + if (binary->info->sp.enable.dvs_6axis) { /* because UV is packed into the Y plane, calc total * YYU size = /2 gives size of UV-only, * total YYU size = UV-only * 3. @@ -3705,8 +3691,7 @@ sh_css_params_write_to_ddr_internal( } } - if (binary->info->sp.enable.ca_gdc) - { + if (binary->info->sp.enable.ca_gdc) { unsigned int i; ia_css_ptr *virt_addr_tetra_x[ @@ -3811,8 +3796,7 @@ sh_css_params_write_to_ddr_internal( } /* After special cases like SC, FPN since they may change parameters */ - for (mem = 0; mem < N_IA_CSS_MEMORIES; mem++) - { + for (mem = 0; mem < N_IA_CSS_MEMORIES; mem++) { const struct ia_css_isp_data *isp_data = ia_css_isp_param_get_isp_mem_init(&binary->info->sp.mem_initializers, IA_CSS_PARAM_CLASS_PARAM, mem); @@ -4025,7 +4009,8 @@ static int write_ia_css_isp_parameter_set_info_to_ddr( static int free_ia_css_isp_parameter_set_info( - ia_css_ptr ptr) { + ia_css_ptr ptr) +{ int err = 0; struct ia_css_isp_parameter_set_info isp_params_info; unsigned int i; @@ -4034,8 +4019,7 @@ free_ia_css_isp_parameter_set_info( IA_CSS_ENTER_PRIVATE("ptr = %u", ptr); /* sanity check - ptr must be valid */ - if (!ia_css_refcount_is_valid(ptr)) - { + if (!ia_css_refcount_is_valid(ptr)) { IA_CSS_ERROR("%s: IA_CSS_REFCOUNT_PARAM_SET_POOL(0x%x) invalid arg", __func__, ptr); err = -EINVAL; @@ -4046,8 +4030,7 @@ free_ia_css_isp_parameter_set_info( hmm_load(ptr, &isp_params_info.mem_map, sizeof(struct sh_css_ddr_address_map)); /* copy map using size info */ for (i = 0; i < (sizeof(struct sh_css_ddr_address_map_size) / - sizeof(size_t)); i++) - { + sizeof(size_t)); i++) { if (addrs[i] == mmgr_NULL) continue; @@ -4254,7 +4237,8 @@ sh_css_update_uds_and_crop_info_based_on_zoom_region( struct sh_css_uds_info *uds, /* out */ struct sh_css_crop_pos *sp_out_crop_pos, /* out */ struct ia_css_resolution pipe_in_res, - bool enable_zoom) { + bool enable_zoom) +{ unsigned int x0 = 0, y0 = 0, x1 = 0, y1 = 0; int err = 0; /* Note: @@ -4285,19 +4269,16 @@ sh_css_update_uds_and_crop_info_based_on_zoom_region( if ((x0 > x1) || (y0 > y1) || (x1 > pipe_in_res.width) || (y1 > pipe_in_res.height)) return -EINVAL; - if (!enable_zoom) - { + if (!enable_zoom) { uds->curr_dx = HRT_GDC_N; uds->curr_dy = HRT_GDC_N; } - if (info->enable.dvs_envelope) - { + if (info->enable.dvs_envelope) { /* Zoom region is only supported by the UDS module on ISP * 2 and higher. It is not supported in video mode on ISP 1 */ return -EINVAL; - } else - { + } else { if (enable_zoom) { /* A. Calculate dx/dy based on crop region using in_frame_info * Scale the crop region if in_frame_info to the stage is not same as diff --git a/drivers/staging/media/atomisp/pci/sh_css_sp.c b/drivers/staging/media/atomisp/pci/sh_css_sp.c index 02f5a73b4096..a73e8ca1e225 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_sp.c +++ b/drivers/staging/media/atomisp/pci/sh_css_sp.c @@ -535,12 +535,12 @@ sh_css_copy_frame_to_spframe(struct ia_css_frame_sp *sp_frame_out, } static int -set_input_frame_buffer(const struct ia_css_frame *frame) { +set_input_frame_buffer(const struct ia_css_frame *frame) +{ if (!frame) return -EINVAL; - switch (frame->info.format) - { + switch (frame->info.format) { case IA_CSS_FRAME_FORMAT_QPLANE6: case IA_CSS_FRAME_FORMAT_YUV420_16: case IA_CSS_FRAME_FORMAT_RAW_PACKED: @@ -566,12 +566,12 @@ set_input_frame_buffer(const struct ia_css_frame *frame) { static int set_output_frame_buffer(const struct ia_css_frame *frame, - unsigned int idx) { + unsigned int idx) +{ if (!frame) return -EINVAL; - switch (frame->info.format) - { + switch (frame->info.format) { case IA_CSS_FRAME_FORMAT_YUV420: case IA_CSS_FRAME_FORMAT_YUV422: case IA_CSS_FRAME_FORMAT_YUV444: @@ -607,12 +607,12 @@ set_output_frame_buffer(const struct ia_css_frame *frame, } static int -set_view_finder_buffer(const struct ia_css_frame *frame) { +set_view_finder_buffer(const struct ia_css_frame *frame) +{ if (!frame) return -EINVAL; - switch (frame->info.format) - { + switch (frame->info.format) { /* the dual output pin */ case IA_CSS_FRAME_FORMAT_NV12: case IA_CSS_FRAME_FORMAT_NV12_16: @@ -732,7 +732,8 @@ sh_css_sp_set_disable_continuous_viewfinder(bool flag) } static int -sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args) { +sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args) +{ int err = 0; int i; @@ -742,8 +743,7 @@ sh_css_sp_write_frame_pointers(const struct sh_css_binary_args *args) { err = set_input_frame_buffer(args->in_frame); if (!err && args->out_vf_frame) err = set_view_finder_buffer(args->out_vf_frame); - for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) - { + for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) { if (!err && args->out_frame[i]) err = set_output_frame_buffer(args->out_frame[i], i); } @@ -786,7 +786,8 @@ sh_css_stage_write_binary_info(struct ia_css_binary_info *info) } static int -copy_isp_mem_if_to_ddr(struct ia_css_binary *binary) { +copy_isp_mem_if_to_ddr(struct ia_css_binary *binary) +{ int err; err = ia_css_isp_param_copy_isp_mem_if_to_ddr( @@ -817,7 +818,8 @@ configure_isp_from_args( const struct ia_css_binary *binary, const struct sh_css_binary_args *args, bool two_ppc, - bool deinterleaved) { + bool deinterleaved) +{ ia_css_fpn_configure(binary, &binary->in_frame_info); ia_css_crop_configure(binary, &args->delay_frames[0]->info); ia_css_qplane_configure(pipeline, binary, &binary->in_frame_info); @@ -896,7 +898,8 @@ sh_css_sp_init_stage(struct ia_css_binary *binary, bool xnr, const struct ia_css_isp_param_css_segments *isp_mem_if, unsigned int if_config_index, - bool two_ppc) { + bool two_ppc) +{ const struct ia_css_binary_xinfo *xinfo; const struct ia_css_binary_info *info; int err = 0; @@ -928,8 +931,7 @@ sh_css_sp_init_stage(struct ia_css_binary *binary, ia_css_pipeline_get_sp_thread_id(pipe_num, &thread_id); - if (!info) - { + if (!info) { sh_css_sp_group.pipe[thread_id].sp_stage_addr[stage] = mmgr_NULL; return 0; } @@ -961,8 +963,7 @@ sh_css_sp_init_stage(struct ia_css_binary *binary, ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.in.info, &binary->in_frame_info); - for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) - { + for (i = 0; i < IA_CSS_BINARY_MAX_OUTPUT_PORTS; i++) { ia_css_frame_info_to_frame_sp_info(&sh_css_sp_stage.frames.out[i].info, &binary->out_frame_info[i]); } @@ -996,16 +997,14 @@ sh_css_sp_init_stage(struct ia_css_binary *binary, err = sh_css_sp_write_frame_pointers(args); /* TODO: move it to a better place */ - if (binary->info->sp.enable.s3a) - { + if (binary->info->sp.enable.s3a) { ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_3A_STATISTICS, thread_id, &queue_id); sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.s3a_buf, queue_id, mmgr_EXCEPTION, IA_CSS_BUFFER_TYPE_3A_STATISTICS); } - if (binary->info->sp.enable.dis) - { + if (binary->info->sp.enable.dis) { ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_DIS_STATISTICS, thread_id, &queue_id); sh_css_copy_buffer_attr_to_spbuffer(&sh_css_sp_stage.frames.dvs_buf, queue_id, @@ -1046,8 +1045,7 @@ sh_css_sp_init_stage(struct ia_css_binary *binary, * the original out res. for video pipe, it has two output pins --- out and * vf_out, so it can keep these two resolutions already. */ if (binary->info->sp.pipeline.mode == IA_CSS_BINARY_MODE_PREVIEW && - (binary->vf_downscale_log2 > 0)) - { + (binary->vf_downscale_log2 > 0)) { /* TODO: Remove this after preview output decimation is fixed * by configuring out&vf info fiels properly */ sh_css_sp_stage.frames.out[0].info.padded_width @@ -1069,7 +1067,8 @@ sp_init_stage(struct ia_css_pipeline_stage *stage, unsigned int pipe_num, bool xnr, unsigned int if_config_index, - bool two_ppc) { + bool two_ppc) +{ struct ia_css_binary *binary; const struct ia_css_fw_info *firmware; const struct sh_css_binary_args *args; @@ -1105,14 +1104,12 @@ sp_init_stage(struct ia_css_pipeline_stage *stage, args = &stage->args; stage_num = stage->stage_num; - if (binary) - { + if (binary) { info = binary->info; binary_name = (const char *)(info->blob->name); blob_info = &info->blob->header.blob; ia_css_init_memory_interface(mem_if, &binary->mem_params, &binary->css_params); - } else if (firmware) - { + } else if (firmware) { const struct ia_css_frame_info *out_infos[IA_CSS_BINARY_MAX_OUTPUT_PORTS] = {NULL}; if (args->out_frame[0]) @@ -1133,8 +1130,7 @@ sp_init_stage(struct ia_css_pipeline_stage *stage, binary_name = IA_CSS_EXT_ISP_PROG_NAME(firmware); blob_info = &firmware->blob; mem_if = (struct ia_css_isp_param_css_segments *)&firmware->mem_initializers; - } else - { + } else { /* SP stage */ assert(stage->sp_func != IA_CSS_PIPELINE_NO_FUNC); /* binary and blob_info are now NULL. @@ -1205,7 +1201,8 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, *internal_frame_origin_bqs_on_sctbl, /* Origin of internal frame positioned on shading table at shading correction in ISP. */ const struct ia_css_isp_parameters *params - ) { + ) +{ /* Get first stage */ struct ia_css_pipeline_stage *stage = NULL; struct ia_css_binary *first_binary = NULL; @@ -1223,17 +1220,14 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, first_binary = me->stages->binary; if (input_mode == IA_CSS_INPUT_MODE_SENSOR || - input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) - { + input_mode == IA_CSS_INPUT_MODE_BUFFERED_SENSOR) { assert(port_id < N_MIPI_PORT_ID); if (port_id >= N_MIPI_PORT_ID) /* should not happen but KW does not know */ return; /* we should be able to return an error */ if_config_index = (uint8_t)(port_id - MIPI_PORT0_ID); - } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY) - { + } else if (input_mode == IA_CSS_INPUT_MODE_MEMORY) { if_config_index = SH_CSS_IF_CONFIG_NOT_NEEDED; - } else - { + } else { if_config_index = 0x0; } @@ -1241,15 +1235,13 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, memset(&sh_css_sp_group.pipe[thread_id], 0, sizeof(struct sh_css_sp_pipeline)); /* Count stages */ - for (stage = me->stages, num = 0; stage; stage = stage->next, num++) - { + for (stage = me->stages, num = 0; stage; stage = stage->next, num++) { stage->stage_num = num; ia_css_debug_pipe_graph_dump_stage(stage, id); } me->num_stages = num; - if (first_binary) - { + if (first_binary) { /* Init pipeline data */ sh_css_sp_init_group(two_ppc, first_binary->input_format, offline, if_config_index); @@ -1277,8 +1269,7 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, /* TODO: next indicates from which queues parameters need to be sampled, needs checking/improvement */ - if (ia_css_pipeline_uses_params(me)) - { + if (ia_css_pipeline_uses_params(me)) { sh_css_sp_group.pipe[thread_id].pipe_config = SH_CSS_PIPE_CONFIG_SAMPLE_PARAMS << thread_id; } @@ -1292,15 +1283,13 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, pipe = find_pipe_by_num(pipe_num); assert(pipe); - if (!pipe) - { + if (!pipe) { return; } sh_css_sp_group.pipe[thread_id].scaler_pp_lut = sh_css_pipe_get_pp_gdc_lut(pipe); #if defined(SH_CSS_ENABLE_METADATA) - if (md_info && md_info->size > 0) - { + if (md_info && md_info->size > 0) { sh_css_sp_group.pipe[thread_id].metadata.width = md_info->resolution.width; sh_css_sp_group.pipe[thread_id].metadata.height = md_info->resolution.height; sh_css_sp_group.pipe[thread_id].metadata.stride = md_info->stride; @@ -1316,8 +1305,7 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, #if defined(SH_CSS_ENABLE_PER_FRAME_PARAMS) sh_css_sp_group.pipe[thread_id].output_frame_queue_id = (uint32_t)SH_CSS_INVALID_QUEUE_ID; - if (pipe_id != IA_CSS_PIPE_ID_COPY) - { + if (pipe_id != IA_CSS_PIPE_ID_COPY) { ia_css_query_internal_queue_id(IA_CSS_BUFFER_TYPE_OUTPUT_FRAME, thread_id, (enum sh_css_queue_id *)( &sh_css_sp_group.pipe[thread_id].output_frame_queue_id)); @@ -1329,14 +1317,12 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, * the parameters are passed to the isp for the shading table centering. */ if (internal_frame_origin_bqs_on_sctbl && - params && params->shading_settings.enable_shading_table_conversion == 0) - { + params && params->shading_settings.enable_shading_table_conversion == 0) { sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl = (uint32_t)internal_frame_origin_bqs_on_sctbl->x; sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl = (uint32_t)internal_frame_origin_bqs_on_sctbl->y; - } else - { + } else { sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_x_bqs_on_sctbl = 0; sh_css_sp_group.pipe[thread_id].shading.internal_frame_origin_y_bqs_on_sctbl = @@ -1347,8 +1333,7 @@ sh_css_sp_init_pipeline(struct ia_css_pipeline *me, IA_CSS_LOG("pipe_id %d port_config %08x", pipe_id, sh_css_sp_group.pipe[thread_id].inout_port_config); - for (stage = me->stages, num = 0; stage; stage = stage->next, num++) - { + for (stage = me->stages, num = 0; stage; stage = stage->next, num++) { sh_css_sp_group.pipe[thread_id].num_stages++; if (is_sp_stage(stage)) { sp_init_sp_stage(stage, pipe_num, two_ppc, @@ -1400,7 +1385,8 @@ bool sh_css_write_host2sp_command(enum host2sp_commands host2sp_command) } enum host2sp_commands -sh_css_read_host2sp_command(void) { +sh_css_read_host2sp_command(void) +{ unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; unsigned int offset = (unsigned int)offsetof(struct host_sp_communication, host2sp_command) / sizeof(int); @@ -1586,7 +1572,8 @@ sh_css_event_init_irq_mask(void) int ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe, unsigned int or_mask, - unsigned int and_mask) { + unsigned int and_mask) +{ unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; unsigned int offset; struct sh_css_event_irq_mask event_irq_mask; @@ -1625,7 +1612,8 @@ ia_css_pipe_set_irq_mask(struct ia_css_pipe *pipe, int ia_css_event_get_irq_mask(const struct ia_css_pipe *pipe, unsigned int *or_mask, - unsigned int *and_mask) { + unsigned int *and_mask) +{ unsigned int HIVE_ADDR_host_sp_com = sh_css_sp_fw.info.sp.host_sp_com; unsigned int offset; struct sh_css_event_irq_mask event_irq_mask; diff --git a/drivers/staging/media/atomisp/pci/sh_css_version.c b/drivers/staging/media/atomisp/pci/sh_css_version.c index fa6de61e4995..f5ff8ca66b50 100644 --- a/drivers/staging/media/atomisp/pci/sh_css_version.c +++ b/drivers/staging/media/atomisp/pci/sh_css_version.c @@ -21,7 +21,8 @@ #include "sh_css_firmware.h" int -ia_css_get_version(char *version, int max_size) { +ia_css_get_version(char *version, int max_size) +{ char *css_version; if (!IS_ISP2401) diff --git a/drivers/staging/media/hantro/Makefile b/drivers/staging/media/hantro/Makefile index 287370188d2a..90036831fec4 100644 --- a/drivers/staging/media/hantro/Makefile +++ b/drivers/staging/media/hantro/Makefile @@ -13,6 +13,7 @@ hantro-vpu-y += \ hantro_g2_hevc_dec.o \ hantro_g1_vp8_dec.o \ rockchip_vpu2_hw_jpeg_enc.o \ + rockchip_vpu2_hw_h264_dec.o \ rockchip_vpu2_hw_mpeg2_dec.o \ rockchip_vpu2_hw_vp8_dec.o \ hantro_jpeg.o \ diff --git a/drivers/staging/media/hantro/hantro.h b/drivers/staging/media/hantro/hantro.h index a70c386de6f1..c2e2dca38628 100644 --- a/drivers/staging/media/hantro/hantro.h +++ b/drivers/staging/media/hantro/hantro.h @@ -61,8 +61,8 @@ struct hantro_irq { * @num_postproc_fmts: Number of post-processor formats. * @codec: Supported codecs * @codec_ops: Codec ops. - * @init: Initialize hardware. - * @runtime_resume: reenable hardware after power gating + * @init: Initialize hardware, optional. + * @runtime_resume: reenable hardware after power gating, optional. * @irqs: array of irq names and interrupt handlers * @num_irqs: number of irqs in the array * @clk_names: array of clock names diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index 31d8449ca1d2..8a2edd67f2c6 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -582,6 +582,7 @@ static const struct v4l2_file_operations hantro_fops = { static const struct of_device_id of_hantro_match[] = { #ifdef CONFIG_VIDEO_HANTRO_ROCKCHIP + { .compatible = "rockchip,px30-vpu", .data = &px30_vpu_variant, }, { .compatible = "rockchip,rk3036-vpu", .data = &rk3036_vpu_variant, }, { .compatible = "rockchip,rk3066-vpu", .data = &rk3066_vpu_variant, }, { .compatible = "rockchip,rk3288-vpu", .data = &rk3288_vpu_variant, }, @@ -942,10 +943,12 @@ static int hantro_probe(struct platform_device *pdev) } } - ret = vpu->variant->init(vpu); - if (ret) { - dev_err(&pdev->dev, "Failed to init VPU hardware\n"); - return ret; + if (vpu->variant->init) { + ret = vpu->variant->init(vpu); + if (ret) { + dev_err(&pdev->dev, "Failed to init VPU hardware\n"); + return ret; + } } pm_runtime_set_autosuspend_delay(vpu->dev, 100); diff --git a/drivers/staging/media/hantro/hantro_g1_h264_dec.c b/drivers/staging/media/hantro/hantro_g1_h264_dec.c index 5c792b7bcb79..236ce24ca00c 100644 --- a/drivers/staging/media/hantro/hantro_g1_h264_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_h264_dec.c @@ -19,13 +19,12 @@ #include "hantro_hw.h" #include "hantro_v4l2.h" -static void set_params(struct hantro_ctx *ctx) +static void set_params(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf) { const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode; const struct v4l2_ctrl_h264_sps *sps = ctrls->sps; const struct v4l2_ctrl_h264_pps *pps = ctrls->pps; - struct vb2_v4l2_buffer *src_buf = hantro_get_src_buf(ctx); struct hantro_dev *vpu = ctx->dev; u32 reg; @@ -127,28 +126,14 @@ static void set_params(struct hantro_ctx *ctx) static void set_ref(struct hantro_ctx *ctx) { - struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; const u8 *b0_reflist, *b1_reflist, *p_reflist; struct hantro_dev *vpu = ctx->dev; - u32 dpb_longterm = 0; - u32 dpb_valid = 0; int reg_num; u32 reg; int i; - /* - * Set up bit maps of valid and long term DPBs. - * NOTE: The bits are reversed, i.e. MSb is DPB 0. - */ - for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { - if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) - dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); - - if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) - dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); - } - vdpu_write_relaxed(vpu, dpb_valid << 16, G1_REG_VALID_REF); - vdpu_write_relaxed(vpu, dpb_longterm << 16, G1_REG_LT_REF); + vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_valid, G1_REG_VALID_REF); + vdpu_write_relaxed(vpu, ctx->h264_dec.dpb_longterm, G1_REG_LT_REF); /* * Set up reference frame picture numbers. @@ -157,17 +142,8 @@ static void set_ref(struct hantro_ctx *ctx) * subsequential reference pictures. */ for (i = 0; i < HANTRO_H264_DPB_SIZE; i += 2) { - reg = 0; - if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) - reg |= G1_REG_REF_PIC_REFER0_NBR(dpb[i].pic_num); - else - reg |= G1_REG_REF_PIC_REFER0_NBR(dpb[i].frame_num); - - if (dpb[i + 1].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) - reg |= G1_REG_REF_PIC_REFER1_NBR(dpb[i + 1].pic_num); - else - reg |= G1_REG_REF_PIC_REFER1_NBR(dpb[i + 1].frame_num); - + reg = G1_REG_REF_PIC_REFER0_NBR(hantro_h264_get_ref_nbr(ctx, i)) | + G1_REG_REF_PIC_REFER1_NBR(hantro_h264_get_ref_nbr(ctx, i + 1)); vdpu_write_relaxed(vpu, reg, G1_REG_REF_PIC(i / 2)); } @@ -226,22 +202,20 @@ static void set_ref(struct hantro_ctx *ctx) } } -static void set_buffers(struct hantro_ctx *ctx) +static void set_buffers(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf) { const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; - struct vb2_v4l2_buffer *src_buf, *dst_buf; + struct vb2_v4l2_buffer *dst_buf; struct hantro_dev *vpu = ctx->dev; dma_addr_t src_dma, dst_dma; size_t offset = 0; - src_buf = hantro_get_src_buf(ctx); - dst_buf = hantro_get_dst_buf(ctx); - /* Source (stream) buffer. */ src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); vdpu_write_relaxed(vpu, src_dma, G1_REG_ADDR_STR); /* Destination (decoded frame) buffer. */ + dst_buf = hantro_get_dst_buf(ctx); dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf); /* Adjust dma addr to start at second line for bottom field */ if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) @@ -276,6 +250,7 @@ static void set_buffers(struct hantro_ctx *ctx) int hantro_g1_h264_dec_run(struct hantro_ctx *ctx) { struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *src_buf; int ret; /* Prepare the H264 decoder context. */ @@ -284,9 +259,10 @@ int hantro_g1_h264_dec_run(struct hantro_ctx *ctx) return ret; /* Configure hardware registers. */ - set_params(ctx); + src_buf = hantro_get_src_buf(ctx); + set_params(ctx, src_buf); set_ref(ctx); - set_buffers(ctx); + set_buffers(ctx, src_buf); hantro_end_prepare_run(ctx); diff --git a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c index 96622a7f8279..6180b23e7d94 100644 --- a/drivers/staging/media/hantro/hantro_g1_vp8_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_vp8_dec.c @@ -367,21 +367,25 @@ static void cfg_tap(struct hantro_ctx *ctx, } static void cfg_ref(struct hantro_ctx *ctx, - const struct v4l2_ctrl_vp8_frame *hdr) + const struct v4l2_ctrl_vp8_frame *hdr, + struct vb2_v4l2_buffer *vb2_dst) { struct hantro_dev *vpu = ctx->dev; - struct vb2_v4l2_buffer *vb2_dst; dma_addr_t ref; - vb2_dst = hantro_get_dst_buf(ctx); ref = hantro_get_ref(ctx, hdr->last_frame_ts); - if (!ref) + if (!ref) { + vpu_debug(0, "failed to find last frame ts=%llu\n", + hdr->last_frame_ts); ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + } vdpu_write_relaxed(vpu, ref, G1_REG_ADDR_REF(0)); ref = hantro_get_ref(ctx, hdr->golden_frame_ts); - WARN_ON(!ref && hdr->golden_frame_ts); + if (!ref && hdr->golden_frame_ts) + vpu_debug(0, "failed to find golden frame ts=%llu\n", + hdr->golden_frame_ts); if (!ref) ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN) @@ -389,7 +393,9 @@ static void cfg_ref(struct hantro_ctx *ctx, vdpu_write_relaxed(vpu, ref, G1_REG_ADDR_REF(4)); ref = hantro_get_ref(ctx, hdr->alt_frame_ts); - WARN_ON(!ref && hdr->alt_frame_ts); + if (!ref && hdr->alt_frame_ts) + vpu_debug(0, "failed to find alt frame ts=%llu\n", + hdr->alt_frame_ts); if (!ref) ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT) @@ -398,16 +404,14 @@ static void cfg_ref(struct hantro_ctx *ctx, } static void cfg_buffers(struct hantro_ctx *ctx, - const struct v4l2_ctrl_vp8_frame *hdr) + const struct v4l2_ctrl_vp8_frame *hdr, + struct vb2_v4l2_buffer *vb2_dst) { const struct v4l2_vp8_segment *seg = &hdr->segment; struct hantro_dev *vpu = ctx->dev; - struct vb2_v4l2_buffer *vb2_dst; dma_addr_t dst_dma; u32 reg; - vb2_dst = hantro_get_dst_buf(ctx); - /* Set probability table buffer address */ vdpu_write_relaxed(vpu, ctx->vp8_dec.prob_tbl.dma, G1_REG_ADDR_QTABLE); @@ -429,6 +433,7 @@ int hantro_g1_vp8_dec_run(struct hantro_ctx *ctx) { const struct v4l2_ctrl_vp8_frame *hdr; struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_dst; size_t height = ctx->dst_fmt.height; size_t width = ctx->dst_fmt.width; u32 mb_width, mb_height; @@ -492,8 +497,10 @@ int hantro_g1_vp8_dec_run(struct hantro_ctx *ctx) cfg_qp(ctx, hdr); cfg_parts(ctx, hdr); cfg_tap(ctx, hdr); - cfg_ref(ctx, hdr); - cfg_buffers(ctx, hdr); + + vb2_dst = hantro_get_dst_buf(ctx); + cfg_ref(ctx, hdr, vb2_dst); + cfg_buffers(ctx, hdr, vb2_dst); hantro_end_prepare_run(ctx); diff --git a/drivers/staging/media/hantro/hantro_h264.c b/drivers/staging/media/hantro/hantro_h264.c index ed6eaf11d96f..0b4d2491be3b 100644 --- a/drivers/staging/media/hantro/hantro_h264.c +++ b/drivers/staging/media/hantro/hantro_h264.c @@ -229,12 +229,25 @@ static void prepare_table(struct hantro_ctx *ctx) const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode; struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu; const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb; + u32 dpb_longterm = 0; + u32 dpb_valid = 0; int i; for (i = 0; i < HANTRO_H264_DPB_SIZE; ++i) { tbl->poc[i * 2] = dpb[i].top_field_order_cnt; tbl->poc[i * 2 + 1] = dpb[i].bottom_field_order_cnt; + + /* + * Set up bit maps of valid and long term DPBs. + * NOTE: The bits are reversed, i.e. MSb is DPB 0. + */ + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) + dpb_valid |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); + if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) + dpb_longterm |= BIT(HANTRO_H264_DPB_SIZE - 1 - i); } + ctx->h264_dec.dpb_valid = dpb_valid << 16; + ctx->h264_dec.dpb_longterm = dpb_longterm << 16; tbl->poc[32] = dec_param->top_field_order_cnt; tbl->poc[33] = dec_param->bottom_field_order_cnt; @@ -335,6 +348,17 @@ dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, return dma_addr; } +u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, unsigned int dpb_idx) +{ + const struct v4l2_h264_dpb_entry *dpb = &ctx->h264_dec.dpb[dpb_idx]; + + if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)) + return 0; + if (dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) + return dpb->pic_num; + return dpb->frame_num; +} + int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx) { struct hantro_h264_dec_hw_ctx *h264_ctx = &ctx->h264_dec; diff --git a/drivers/staging/media/hantro/hantro_hw.h b/drivers/staging/media/hantro/hantro_hw.h index 5dcf65805396..df7b5e3a57b9 100644 --- a/drivers/staging/media/hantro/hantro_hw.h +++ b/drivers/staging/media/hantro/hantro_hw.h @@ -89,12 +89,16 @@ struct hantro_h264_dec_reflists { * @dpb: DPB * @reflists: P/B0/B1 reflists * @ctrls: V4L2 controls attached to a run + * @dpb_longterm: DPB long-term + * @dpb_valid: DPB valid */ struct hantro_h264_dec_hw_ctx { struct hantro_aux_buf priv; struct v4l2_h264_dpb_entry dpb[HANTRO_H264_DPB_SIZE]; struct hantro_h264_dec_reflists reflists; struct hantro_h264_dec_ctrls ctrls; + u32 dpb_longterm; + u32 dpb_valid; }; /** @@ -205,6 +209,7 @@ enum hantro_enc_fmt { extern const struct hantro_variant imx8mq_vpu_g2_variant; extern const struct hantro_variant imx8mq_vpu_variant; +extern const struct hantro_variant px30_vpu_variant; extern const struct hantro_variant rk3036_vpu_variant; extern const struct hantro_variant rk3066_vpu_variant; extern const struct hantro_variant rk3288_vpu_variant; @@ -234,7 +239,10 @@ void hantro_jpeg_enc_done(struct hantro_ctx *ctx); dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx, unsigned int dpb_idx); +u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, + unsigned int dpb_idx); int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx); +int rockchip_vpu2_h264_dec_run(struct hantro_ctx *ctx); int hantro_g1_h264_dec_run(struct hantro_ctx *ctx); int hantro_h264_dec_init(struct hantro_ctx *ctx); void hantro_h264_dec_exit(struct hantro_ctx *ctx); diff --git a/drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c new file mode 100644 index 000000000000..64a6330475eb --- /dev/null +++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_h264_dec.c @@ -0,0 +1,491 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Hantro VPU codec driver + * + * Copyright (c) 2014 Rockchip Electronics Co., Ltd. + * Hertz Wong <hertz.wong@rock-chips.com> + * Herman Chen <herman.chen@rock-chips.com> + * + * Copyright (C) 2014 Google, Inc. + * Tomasz Figa <tfiga@chromium.org> + */ + +#include <linux/types.h> +#include <linux/sort.h> + +#include <media/v4l2-mem2mem.h> + +#include "hantro_hw.h" +#include "hantro_v4l2.h" + +#define VDPU_SWREG(nr) ((nr) * 4) + +#define VDPU_REG_DEC_OUT_BASE VDPU_SWREG(63) +#define VDPU_REG_RLC_VLC_BASE VDPU_SWREG(64) +#define VDPU_REG_QTABLE_BASE VDPU_SWREG(61) +#define VDPU_REG_DIR_MV_BASE VDPU_SWREG(62) +#define VDPU_REG_REFER_BASE(i) (VDPU_SWREG(84 + (i))) +#define VDPU_REG_DEC_E(v) ((v) ? BIT(0) : 0) + +#define VDPU_REG_DEC_ADV_PRE_DIS(v) ((v) ? BIT(11) : 0) +#define VDPU_REG_DEC_SCMD_DIS(v) ((v) ? BIT(10) : 0) +#define VDPU_REG_FILTERING_DIS(v) ((v) ? BIT(8) : 0) +#define VDPU_REG_PIC_FIXED_QUANT(v) ((v) ? BIT(7) : 0) +#define VDPU_REG_DEC_LATENCY(v) (((v) << 1) & GENMASK(6, 1)) + +#define VDPU_REG_INIT_QP(v) (((v) << 25) & GENMASK(30, 25)) +#define VDPU_REG_STREAM_LEN(v) (((v) << 0) & GENMASK(23, 0)) + +#define VDPU_REG_APF_THRESHOLD(v) (((v) << 17) & GENMASK(30, 17)) +#define VDPU_REG_STARTMB_X(v) (((v) << 8) & GENMASK(16, 8)) +#define VDPU_REG_STARTMB_Y(v) (((v) << 0) & GENMASK(7, 0)) + +#define VDPU_REG_DEC_MODE(v) (((v) << 0) & GENMASK(3, 0)) + +#define VDPU_REG_DEC_STRENDIAN_E(v) ((v) ? BIT(5) : 0) +#define VDPU_REG_DEC_STRSWAP32_E(v) ((v) ? BIT(4) : 0) +#define VDPU_REG_DEC_OUTSWAP32_E(v) ((v) ? BIT(3) : 0) +#define VDPU_REG_DEC_INSWAP32_E(v) ((v) ? BIT(2) : 0) +#define VDPU_REG_DEC_OUT_ENDIAN(v) ((v) ? BIT(1) : 0) +#define VDPU_REG_DEC_IN_ENDIAN(v) ((v) ? BIT(0) : 0) + +#define VDPU_REG_DEC_DATA_DISC_E(v) ((v) ? BIT(22) : 0) +#define VDPU_REG_DEC_MAX_BURST(v) (((v) << 16) & GENMASK(20, 16)) +#define VDPU_REG_DEC_AXI_WR_ID(v) (((v) << 8) & GENMASK(15, 8)) +#define VDPU_REG_DEC_AXI_RD_ID(v) (((v) << 0) & GENMASK(7, 0)) + +#define VDPU_REG_START_CODE_E(v) ((v) ? BIT(22) : 0) +#define VDPU_REG_CH_8PIX_ILEAV_E(v) ((v) ? BIT(21) : 0) +#define VDPU_REG_RLC_MODE_E(v) ((v) ? BIT(20) : 0) +#define VDPU_REG_PIC_INTERLACE_E(v) ((v) ? BIT(17) : 0) +#define VDPU_REG_PIC_FIELDMODE_E(v) ((v) ? BIT(16) : 0) +#define VDPU_REG_PIC_TOPFIELD_E(v) ((v) ? BIT(13) : 0) +#define VDPU_REG_WRITE_MVS_E(v) ((v) ? BIT(10) : 0) +#define VDPU_REG_SEQ_MBAFF_E(v) ((v) ? BIT(7) : 0) +#define VDPU_REG_PICORD_COUNT_E(v) ((v) ? BIT(6) : 0) +#define VDPU_REG_DEC_TIMEOUT_E(v) ((v) ? BIT(5) : 0) +#define VDPU_REG_DEC_CLK_GATE_E(v) ((v) ? BIT(4) : 0) + +#define VDPU_REG_PRED_BC_TAP_0_0(v) (((v) << 22) & GENMASK(31, 22)) +#define VDPU_REG_PRED_BC_TAP_0_1(v) (((v) << 12) & GENMASK(21, 12)) +#define VDPU_REG_PRED_BC_TAP_0_2(v) (((v) << 2) & GENMASK(11, 2)) + +#define VDPU_REG_REFBU_E(v) ((v) ? BIT(31) : 0) + +#define VDPU_REG_PINIT_RLIST_F9(v) (((v) << 25) & GENMASK(29, 25)) +#define VDPU_REG_PINIT_RLIST_F8(v) (((v) << 20) & GENMASK(24, 20)) +#define VDPU_REG_PINIT_RLIST_F7(v) (((v) << 15) & GENMASK(19, 15)) +#define VDPU_REG_PINIT_RLIST_F6(v) (((v) << 10) & GENMASK(14, 10)) +#define VDPU_REG_PINIT_RLIST_F5(v) (((v) << 5) & GENMASK(9, 5)) +#define VDPU_REG_PINIT_RLIST_F4(v) (((v) << 0) & GENMASK(4, 0)) + +#define VDPU_REG_PINIT_RLIST_F15(v) (((v) << 25) & GENMASK(29, 25)) +#define VDPU_REG_PINIT_RLIST_F14(v) (((v) << 20) & GENMASK(24, 20)) +#define VDPU_REG_PINIT_RLIST_F13(v) (((v) << 15) & GENMASK(19, 15)) +#define VDPU_REG_PINIT_RLIST_F12(v) (((v) << 10) & GENMASK(14, 10)) +#define VDPU_REG_PINIT_RLIST_F11(v) (((v) << 5) & GENMASK(9, 5)) +#define VDPU_REG_PINIT_RLIST_F10(v) (((v) << 0) & GENMASK(4, 0)) + +#define VDPU_REG_REFER1_NBR(v) (((v) << 16) & GENMASK(31, 16)) +#define VDPU_REG_REFER0_NBR(v) (((v) << 0) & GENMASK(15, 0)) + +#define VDPU_REG_REFER3_NBR(v) (((v) << 16) & GENMASK(31, 16)) +#define VDPU_REG_REFER2_NBR(v) (((v) << 0) & GENMASK(15, 0)) + +#define VDPU_REG_REFER5_NBR(v) (((v) << 16) & GENMASK(31, 16)) +#define VDPU_REG_REFER4_NBR(v) (((v) << 0) & GENMASK(15, 0)) + +#define VDPU_REG_REFER7_NBR(v) (((v) << 16) & GENMASK(31, 16)) +#define VDPU_REG_REFER6_NBR(v) (((v) << 0) & GENMASK(15, 0)) + +#define VDPU_REG_REFER9_NBR(v) (((v) << 16) & GENMASK(31, 16)) +#define VDPU_REG_REFER8_NBR(v) (((v) << 0) & GENMASK(15, 0)) + +#define VDPU_REG_REFER11_NBR(v) (((v) << 16) & GENMASK(31, 16)) +#define VDPU_REG_REFER10_NBR(v) (((v) << 0) & GENMASK(15, 0)) + +#define VDPU_REG_REFER13_NBR(v) (((v) << 16) & GENMASK(31, 16)) +#define VDPU_REG_REFER12_NBR(v) (((v) << 0) & GENMASK(15, 0)) + +#define VDPU_REG_REFER15_NBR(v) (((v) << 16) & GENMASK(31, 16)) +#define VDPU_REG_REFER14_NBR(v) (((v) << 0) & GENMASK(15, 0)) + +#define VDPU_REG_BINIT_RLIST_F5(v) (((v) << 25) & GENMASK(29, 25)) +#define VDPU_REG_BINIT_RLIST_F4(v) (((v) << 20) & GENMASK(24, 20)) +#define VDPU_REG_BINIT_RLIST_F3(v) (((v) << 15) & GENMASK(19, 15)) +#define VDPU_REG_BINIT_RLIST_F2(v) (((v) << 10) & GENMASK(14, 10)) +#define VDPU_REG_BINIT_RLIST_F1(v) (((v) << 5) & GENMASK(9, 5)) +#define VDPU_REG_BINIT_RLIST_F0(v) (((v) << 0) & GENMASK(4, 0)) + +#define VDPU_REG_BINIT_RLIST_F11(v) (((v) << 25) & GENMASK(29, 25)) +#define VDPU_REG_BINIT_RLIST_F10(v) (((v) << 20) & GENMASK(24, 20)) +#define VDPU_REG_BINIT_RLIST_F9(v) (((v) << 15) & GENMASK(19, 15)) +#define VDPU_REG_BINIT_RLIST_F8(v) (((v) << 10) & GENMASK(14, 10)) +#define VDPU_REG_BINIT_RLIST_F7(v) (((v) << 5) & GENMASK(9, 5)) +#define VDPU_REG_BINIT_RLIST_F6(v) (((v) << 0) & GENMASK(4, 0)) + +#define VDPU_REG_BINIT_RLIST_F15(v) (((v) << 15) & GENMASK(19, 15)) +#define VDPU_REG_BINIT_RLIST_F14(v) (((v) << 10) & GENMASK(14, 10)) +#define VDPU_REG_BINIT_RLIST_F13(v) (((v) << 5) & GENMASK(9, 5)) +#define VDPU_REG_BINIT_RLIST_F12(v) (((v) << 0) & GENMASK(4, 0)) + +#define VDPU_REG_BINIT_RLIST_B5(v) (((v) << 25) & GENMASK(29, 25)) +#define VDPU_REG_BINIT_RLIST_B4(v) (((v) << 20) & GENMASK(24, 20)) +#define VDPU_REG_BINIT_RLIST_B3(v) (((v) << 15) & GENMASK(19, 15)) +#define VDPU_REG_BINIT_RLIST_B2(v) (((v) << 10) & GENMASK(14, 10)) +#define VDPU_REG_BINIT_RLIST_B1(v) (((v) << 5) & GENMASK(9, 5)) +#define VDPU_REG_BINIT_RLIST_B0(v) (((v) << 0) & GENMASK(4, 0)) + +#define VDPU_REG_BINIT_RLIST_B11(v) (((v) << 25) & GENMASK(29, 25)) +#define VDPU_REG_BINIT_RLIST_B10(v) (((v) << 20) & GENMASK(24, 20)) +#define VDPU_REG_BINIT_RLIST_B9(v) (((v) << 15) & GENMASK(19, 15)) +#define VDPU_REG_BINIT_RLIST_B8(v) (((v) << 10) & GENMASK(14, 10)) +#define VDPU_REG_BINIT_RLIST_B7(v) (((v) << 5) & GENMASK(9, 5)) +#define VDPU_REG_BINIT_RLIST_B6(v) (((v) << 0) & GENMASK(4, 0)) + +#define VDPU_REG_BINIT_RLIST_B15(v) (((v) << 15) & GENMASK(19, 15)) +#define VDPU_REG_BINIT_RLIST_B14(v) (((v) << 10) & GENMASK(14, 10)) +#define VDPU_REG_BINIT_RLIST_B13(v) (((v) << 5) & GENMASK(9, 5)) +#define VDPU_REG_BINIT_RLIST_B12(v) (((v) << 0) & GENMASK(4, 0)) + +#define VDPU_REG_PINIT_RLIST_F3(v) (((v) << 15) & GENMASK(19, 15)) +#define VDPU_REG_PINIT_RLIST_F2(v) (((v) << 10) & GENMASK(14, 10)) +#define VDPU_REG_PINIT_RLIST_F1(v) (((v) << 5) & GENMASK(9, 5)) +#define VDPU_REG_PINIT_RLIST_F0(v) (((v) << 0) & GENMASK(4, 0)) + +#define VDPU_REG_REFER_LTERM_E(v) (((v) << 0) & GENMASK(31, 0)) + +#define VDPU_REG_REFER_VALID_E(v) (((v) << 0) & GENMASK(31, 0)) + +#define VDPU_REG_STRM_START_BIT(v) (((v) << 0) & GENMASK(5, 0)) + +#define VDPU_REG_CH_QP_OFFSET2(v) (((v) << 22) & GENMASK(26, 22)) +#define VDPU_REG_CH_QP_OFFSET(v) (((v) << 17) & GENMASK(21, 17)) +#define VDPU_REG_PIC_MB_HEIGHT_P(v) (((v) << 9) & GENMASK(16, 9)) +#define VDPU_REG_PIC_MB_WIDTH(v) (((v) << 0) & GENMASK(8, 0)) + +#define VDPU_REG_WEIGHT_BIPR_IDC(v) (((v) << 16) & GENMASK(17, 16)) +#define VDPU_REG_REF_FRAMES(v) (((v) << 0) & GENMASK(4, 0)) + +#define VDPU_REG_FILT_CTRL_PRES(v) ((v) ? BIT(31) : 0) +#define VDPU_REG_RDPIC_CNT_PRES(v) ((v) ? BIT(30) : 0) +#define VDPU_REG_FRAMENUM_LEN(v) (((v) << 16) & GENMASK(20, 16)) +#define VDPU_REG_FRAMENUM(v) (((v) << 0) & GENMASK(15, 0)) + +#define VDPU_REG_REFPIC_MK_LEN(v) (((v) << 16) & GENMASK(26, 16)) +#define VDPU_REG_IDR_PIC_ID(v) (((v) << 0) & GENMASK(15, 0)) + +#define VDPU_REG_PPS_ID(v) (((v) << 24) & GENMASK(31, 24)) +#define VDPU_REG_REFIDX1_ACTIVE(v) (((v) << 19) & GENMASK(23, 19)) +#define VDPU_REG_REFIDX0_ACTIVE(v) (((v) << 14) & GENMASK(18, 14)) +#define VDPU_REG_POC_LENGTH(v) (((v) << 0) & GENMASK(7, 0)) + +#define VDPU_REG_IDR_PIC_E(v) ((v) ? BIT(8) : 0) +#define VDPU_REG_DIR_8X8_INFER_E(v) ((v) ? BIT(7) : 0) +#define VDPU_REG_BLACKWHITE_E(v) ((v) ? BIT(6) : 0) +#define VDPU_REG_CABAC_E(v) ((v) ? BIT(5) : 0) +#define VDPU_REG_WEIGHT_PRED_E(v) ((v) ? BIT(4) : 0) +#define VDPU_REG_CONST_INTRA_E(v) ((v) ? BIT(3) : 0) +#define VDPU_REG_8X8TRANS_FLAG_E(v) ((v) ? BIT(2) : 0) +#define VDPU_REG_TYPE1_QUANT_E(v) ((v) ? BIT(1) : 0) +#define VDPU_REG_FIELDPIC_FLAG_E(v) ((v) ? BIT(0) : 0) + +static void set_params(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf) +{ + const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; + const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode; + const struct v4l2_ctrl_h264_sps *sps = ctrls->sps; + const struct v4l2_ctrl_h264_pps *pps = ctrls->pps; + struct hantro_dev *vpu = ctx->dev; + u32 reg; + + reg = VDPU_REG_DEC_ADV_PRE_DIS(0) | + VDPU_REG_DEC_SCMD_DIS(0) | + VDPU_REG_FILTERING_DIS(0) | + VDPU_REG_PIC_FIXED_QUANT(0) | + VDPU_REG_DEC_LATENCY(0); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(50)); + + reg = VDPU_REG_INIT_QP(pps->pic_init_qp_minus26 + 26) | + VDPU_REG_STREAM_LEN(vb2_get_plane_payload(&src_buf->vb2_buf, 0)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(51)); + + reg = VDPU_REG_APF_THRESHOLD(8) | + VDPU_REG_STARTMB_X(0) | + VDPU_REG_STARTMB_Y(0); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(52)); + + reg = VDPU_REG_DEC_MODE(0); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(53)); + + reg = VDPU_REG_DEC_STRENDIAN_E(1) | + VDPU_REG_DEC_STRSWAP32_E(1) | + VDPU_REG_DEC_OUTSWAP32_E(1) | + VDPU_REG_DEC_INSWAP32_E(1) | + VDPU_REG_DEC_OUT_ENDIAN(1) | + VDPU_REG_DEC_IN_ENDIAN(0); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(54)); + + reg = VDPU_REG_DEC_DATA_DISC_E(0) | + VDPU_REG_DEC_MAX_BURST(16) | + VDPU_REG_DEC_AXI_WR_ID(0) | + VDPU_REG_DEC_AXI_RD_ID(0xff); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(56)); + + reg = VDPU_REG_START_CODE_E(1) | + VDPU_REG_CH_8PIX_ILEAV_E(0) | + VDPU_REG_RLC_MODE_E(0) | + VDPU_REG_PIC_INTERLACE_E(!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) && + (sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD || + dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC)) | + VDPU_REG_PIC_FIELDMODE_E(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) | + VDPU_REG_PIC_TOPFIELD_E(!(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD)) | + VDPU_REG_WRITE_MVS_E((sps->profile_idc > 66) && dec_param->nal_ref_idc) | + VDPU_REG_SEQ_MBAFF_E(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD) | + VDPU_REG_PICORD_COUNT_E(sps->profile_idc > 66) | + VDPU_REG_DEC_TIMEOUT_E(1) | + VDPU_REG_DEC_CLK_GATE_E(1); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(57)); + + reg = VDPU_REG_PRED_BC_TAP_0_0(1) | + VDPU_REG_PRED_BC_TAP_0_1((u32)-5) | + VDPU_REG_PRED_BC_TAP_0_2(20); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(59)); + + reg = VDPU_REG_REFBU_E(0); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(65)); + + reg = VDPU_REG_STRM_START_BIT(0); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(109)); + + reg = VDPU_REG_CH_QP_OFFSET2(pps->second_chroma_qp_index_offset) | + VDPU_REG_CH_QP_OFFSET(pps->chroma_qp_index_offset) | + VDPU_REG_PIC_MB_HEIGHT_P(MB_HEIGHT(ctx->src_fmt.height)) | + VDPU_REG_PIC_MB_WIDTH(MB_WIDTH(ctx->src_fmt.width)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(110)); + + reg = VDPU_REG_WEIGHT_BIPR_IDC(pps->weighted_bipred_idc) | + VDPU_REG_REF_FRAMES(sps->max_num_ref_frames); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(111)); + + reg = VDPU_REG_FILT_CTRL_PRES(pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT) | + VDPU_REG_RDPIC_CNT_PRES(pps->flags & V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT) | + VDPU_REG_FRAMENUM_LEN(sps->log2_max_frame_num_minus4 + 4) | + VDPU_REG_FRAMENUM(dec_param->frame_num); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(112)); + + reg = VDPU_REG_REFPIC_MK_LEN(dec_param->dec_ref_pic_marking_bit_size) | + VDPU_REG_IDR_PIC_ID(dec_param->idr_pic_id); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(113)); + + reg = VDPU_REG_PPS_ID(pps->pic_parameter_set_id) | + VDPU_REG_REFIDX1_ACTIVE(pps->num_ref_idx_l1_default_active_minus1 + 1) | + VDPU_REG_REFIDX0_ACTIVE(pps->num_ref_idx_l0_default_active_minus1 + 1) | + VDPU_REG_POC_LENGTH(dec_param->pic_order_cnt_bit_size); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(114)); + + reg = VDPU_REG_IDR_PIC_E(dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC) | + VDPU_REG_DIR_8X8_INFER_E(sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE) | + VDPU_REG_BLACKWHITE_E(sps->profile_idc >= 100 && sps->chroma_format_idc == 0) | + VDPU_REG_CABAC_E(pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE) | + VDPU_REG_WEIGHT_PRED_E(pps->flags & V4L2_H264_PPS_FLAG_WEIGHTED_PRED) | + VDPU_REG_CONST_INTRA_E(pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED) | + VDPU_REG_8X8TRANS_FLAG_E(pps->flags & V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE) | + VDPU_REG_TYPE1_QUANT_E(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT) | + VDPU_REG_FIELDPIC_FLAG_E(!(sps->flags & V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(115)); +} + +static void set_ref(struct hantro_ctx *ctx) +{ + const u8 *b0_reflist, *b1_reflist, *p_reflist; + struct hantro_dev *vpu = ctx->dev; + u32 reg; + int i; + + b0_reflist = ctx->h264_dec.reflists.b0; + b1_reflist = ctx->h264_dec.reflists.b1; + p_reflist = ctx->h264_dec.reflists.p; + + reg = VDPU_REG_PINIT_RLIST_F9(p_reflist[9]) | + VDPU_REG_PINIT_RLIST_F8(p_reflist[8]) | + VDPU_REG_PINIT_RLIST_F7(p_reflist[7]) | + VDPU_REG_PINIT_RLIST_F6(p_reflist[6]) | + VDPU_REG_PINIT_RLIST_F5(p_reflist[5]) | + VDPU_REG_PINIT_RLIST_F4(p_reflist[4]); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(74)); + + reg = VDPU_REG_PINIT_RLIST_F15(p_reflist[15]) | + VDPU_REG_PINIT_RLIST_F14(p_reflist[14]) | + VDPU_REG_PINIT_RLIST_F13(p_reflist[13]) | + VDPU_REG_PINIT_RLIST_F12(p_reflist[12]) | + VDPU_REG_PINIT_RLIST_F11(p_reflist[11]) | + VDPU_REG_PINIT_RLIST_F10(p_reflist[10]); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(75)); + + reg = VDPU_REG_REFER1_NBR(hantro_h264_get_ref_nbr(ctx, 1)) | + VDPU_REG_REFER0_NBR(hantro_h264_get_ref_nbr(ctx, 0)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(76)); + + reg = VDPU_REG_REFER3_NBR(hantro_h264_get_ref_nbr(ctx, 3)) | + VDPU_REG_REFER2_NBR(hantro_h264_get_ref_nbr(ctx, 2)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(77)); + + reg = VDPU_REG_REFER5_NBR(hantro_h264_get_ref_nbr(ctx, 5)) | + VDPU_REG_REFER4_NBR(hantro_h264_get_ref_nbr(ctx, 4)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(78)); + + reg = VDPU_REG_REFER7_NBR(hantro_h264_get_ref_nbr(ctx, 7)) | + VDPU_REG_REFER6_NBR(hantro_h264_get_ref_nbr(ctx, 6)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(79)); + + reg = VDPU_REG_REFER9_NBR(hantro_h264_get_ref_nbr(ctx, 9)) | + VDPU_REG_REFER8_NBR(hantro_h264_get_ref_nbr(ctx, 8)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(80)); + + reg = VDPU_REG_REFER11_NBR(hantro_h264_get_ref_nbr(ctx, 11)) | + VDPU_REG_REFER10_NBR(hantro_h264_get_ref_nbr(ctx, 10)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(81)); + + reg = VDPU_REG_REFER13_NBR(hantro_h264_get_ref_nbr(ctx, 13)) | + VDPU_REG_REFER12_NBR(hantro_h264_get_ref_nbr(ctx, 12)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(82)); + + reg = VDPU_REG_REFER15_NBR(hantro_h264_get_ref_nbr(ctx, 15)) | + VDPU_REG_REFER14_NBR(hantro_h264_get_ref_nbr(ctx, 14)); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(83)); + + reg = VDPU_REG_BINIT_RLIST_F5(b0_reflist[5]) | + VDPU_REG_BINIT_RLIST_F4(b0_reflist[4]) | + VDPU_REG_BINIT_RLIST_F3(b0_reflist[3]) | + VDPU_REG_BINIT_RLIST_F2(b0_reflist[2]) | + VDPU_REG_BINIT_RLIST_F1(b0_reflist[1]) | + VDPU_REG_BINIT_RLIST_F0(b0_reflist[0]); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(100)); + + reg = VDPU_REG_BINIT_RLIST_F11(b0_reflist[11]) | + VDPU_REG_BINIT_RLIST_F10(b0_reflist[10]) | + VDPU_REG_BINIT_RLIST_F9(b0_reflist[9]) | + VDPU_REG_BINIT_RLIST_F8(b0_reflist[8]) | + VDPU_REG_BINIT_RLIST_F7(b0_reflist[7]) | + VDPU_REG_BINIT_RLIST_F6(b0_reflist[6]); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(101)); + + reg = VDPU_REG_BINIT_RLIST_F15(b0_reflist[15]) | + VDPU_REG_BINIT_RLIST_F14(b0_reflist[14]) | + VDPU_REG_BINIT_RLIST_F13(b0_reflist[13]) | + VDPU_REG_BINIT_RLIST_F12(b0_reflist[12]); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(102)); + + reg = VDPU_REG_BINIT_RLIST_B5(b1_reflist[5]) | + VDPU_REG_BINIT_RLIST_B4(b1_reflist[4]) | + VDPU_REG_BINIT_RLIST_B3(b1_reflist[3]) | + VDPU_REG_BINIT_RLIST_B2(b1_reflist[2]) | + VDPU_REG_BINIT_RLIST_B1(b1_reflist[1]) | + VDPU_REG_BINIT_RLIST_B0(b1_reflist[0]); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(103)); + + reg = VDPU_REG_BINIT_RLIST_B11(b1_reflist[11]) | + VDPU_REG_BINIT_RLIST_B10(b1_reflist[10]) | + VDPU_REG_BINIT_RLIST_B9(b1_reflist[9]) | + VDPU_REG_BINIT_RLIST_B8(b1_reflist[8]) | + VDPU_REG_BINIT_RLIST_B7(b1_reflist[7]) | + VDPU_REG_BINIT_RLIST_B6(b1_reflist[6]); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(104)); + + reg = VDPU_REG_BINIT_RLIST_B15(b1_reflist[15]) | + VDPU_REG_BINIT_RLIST_B14(b1_reflist[14]) | + VDPU_REG_BINIT_RLIST_B13(b1_reflist[13]) | + VDPU_REG_BINIT_RLIST_B12(b1_reflist[12]); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(105)); + + reg = VDPU_REG_PINIT_RLIST_F3(p_reflist[3]) | + VDPU_REG_PINIT_RLIST_F2(p_reflist[2]) | + VDPU_REG_PINIT_RLIST_F1(p_reflist[1]) | + VDPU_REG_PINIT_RLIST_F0(p_reflist[0]); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(106)); + + reg = VDPU_REG_REFER_LTERM_E(ctx->h264_dec.dpb_longterm); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(107)); + + reg = VDPU_REG_REFER_VALID_E(ctx->h264_dec.dpb_valid); + vdpu_write_relaxed(vpu, reg, VDPU_SWREG(108)); + + /* Set up addresses of DPB buffers. */ + for (i = 0; i < HANTRO_H264_DPB_SIZE; i++) { + dma_addr_t dma_addr = hantro_h264_get_ref_buf(ctx, i); + + vdpu_write_relaxed(vpu, dma_addr, VDPU_REG_REFER_BASE(i)); + } +} + +static void set_buffers(struct hantro_ctx *ctx, struct vb2_v4l2_buffer *src_buf) +{ + const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls; + struct vb2_v4l2_buffer *dst_buf; + struct hantro_dev *vpu = ctx->dev; + dma_addr_t src_dma, dst_dma; + size_t offset = 0; + + /* Source (stream) buffer. */ + src_dma = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0); + vdpu_write_relaxed(vpu, src_dma, VDPU_REG_RLC_VLC_BASE); + + /* Destination (decoded frame) buffer. */ + dst_buf = hantro_get_dst_buf(ctx); + dst_dma = hantro_get_dec_buf_addr(ctx, &dst_buf->vb2_buf); + /* Adjust dma addr to start at second line for bottom field */ + if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + offset = ALIGN(ctx->src_fmt.width, MB_DIM); + vdpu_write_relaxed(vpu, dst_dma + offset, VDPU_REG_DEC_OUT_BASE); + + /* Higher profiles require DMV buffer appended to reference frames. */ + if (ctrls->sps->profile_idc > 66 && ctrls->decode->nal_ref_idc) { + unsigned int bytes_per_mb = 384; + + /* DMV buffer for monochrome start directly after Y-plane */ + if (ctrls->sps->profile_idc >= 100 && + ctrls->sps->chroma_format_idc == 0) + bytes_per_mb = 256; + offset = bytes_per_mb * MB_WIDTH(ctx->src_fmt.width) * + MB_HEIGHT(ctx->src_fmt.height); + + /* + * DMV buffer is split in two for field encoded frames, + * adjust offset for bottom field + */ + if (ctrls->decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BOTTOM_FIELD) + offset += 32 * MB_WIDTH(ctx->src_fmt.width) * + MB_HEIGHT(ctx->src_fmt.height); + vdpu_write_relaxed(vpu, dst_dma + offset, VDPU_REG_DIR_MV_BASE); + } + + /* Auxiliary buffer prepared in hantro_g1_h264_dec_prepare_table(). */ + vdpu_write_relaxed(vpu, ctx->h264_dec.priv.dma, VDPU_REG_QTABLE_BASE); +} + +int rockchip_vpu2_h264_dec_run(struct hantro_ctx *ctx) +{ + struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *src_buf; + u32 reg; + int ret; + + /* Prepare the H264 decoder context. */ + ret = hantro_h264_dec_prepare_run(ctx); + if (ret) + return ret; + + src_buf = hantro_get_src_buf(ctx); + set_params(ctx, src_buf); + set_ref(ctx); + set_buffers(ctx, src_buf); + + hantro_end_prepare_run(ctx); + + /* Start decoding! */ + reg = vdpu_read(vpu, VDPU_SWREG(57)) | VDPU_REG_DEC_E(1); + vdpu_write(vpu, reg, VDPU_SWREG(57)); + + return 0; +} diff --git a/drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c b/drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c index 951b55f58a61..d079075448c9 100644 --- a/drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c +++ b/drivers/staging/media/hantro/rockchip_vpu2_hw_vp8_dec.c @@ -444,21 +444,24 @@ static void cfg_tap(struct hantro_ctx *ctx, } static void cfg_ref(struct hantro_ctx *ctx, - const struct v4l2_ctrl_vp8_frame *hdr) + const struct v4l2_ctrl_vp8_frame *hdr, + struct vb2_v4l2_buffer *vb2_dst) { struct hantro_dev *vpu = ctx->dev; - struct vb2_v4l2_buffer *vb2_dst; dma_addr_t ref; - vb2_dst = hantro_get_dst_buf(ctx); - ref = hantro_get_ref(ctx, hdr->last_frame_ts); - if (!ref) + if (!ref) { + vpu_debug(0, "failed to find last frame ts=%llu\n", + hdr->last_frame_ts); ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); + } vdpu_write_relaxed(vpu, ref, VDPU_REG_VP8_ADDR_REF0); ref = hantro_get_ref(ctx, hdr->golden_frame_ts); - WARN_ON(!ref && hdr->golden_frame_ts); + if (!ref && hdr->golden_frame_ts) + vpu_debug(0, "failed to find golden frame ts=%llu\n", + hdr->golden_frame_ts); if (!ref) ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_GOLDEN) @@ -466,7 +469,9 @@ static void cfg_ref(struct hantro_ctx *ctx, vdpu_write_relaxed(vpu, ref, VDPU_REG_VP8_ADDR_REF2_5(2)); ref = hantro_get_ref(ctx, hdr->alt_frame_ts); - WARN_ON(!ref && hdr->alt_frame_ts); + if (!ref && hdr->alt_frame_ts) + vpu_debug(0, "failed to find alt frame ts=%llu\n", + hdr->alt_frame_ts); if (!ref) ref = vb2_dma_contig_plane_dma_addr(&vb2_dst->vb2_buf, 0); if (hdr->flags & V4L2_VP8_FRAME_FLAG_SIGN_BIAS_ALT) @@ -475,16 +480,14 @@ static void cfg_ref(struct hantro_ctx *ctx, } static void cfg_buffers(struct hantro_ctx *ctx, - const struct v4l2_ctrl_vp8_frame *hdr) + const struct v4l2_ctrl_vp8_frame *hdr, + struct vb2_v4l2_buffer *vb2_dst) { const struct v4l2_vp8_segment *seg = &hdr->segment; struct hantro_dev *vpu = ctx->dev; - struct vb2_v4l2_buffer *vb2_dst; dma_addr_t dst_dma; u32 reg; - vb2_dst = hantro_get_dst_buf(ctx); - /* Set probability table buffer address */ vdpu_write_relaxed(vpu, ctx->vp8_dec.prob_tbl.dma, VDPU_REG_ADDR_QTABLE); @@ -507,6 +510,7 @@ int rockchip_vpu2_vp8_dec_run(struct hantro_ctx *ctx) { const struct v4l2_ctrl_vp8_frame *hdr; struct hantro_dev *vpu = ctx->dev; + struct vb2_v4l2_buffer *vb2_dst; size_t height = ctx->dst_fmt.height; size_t width = ctx->dst_fmt.width; u32 mb_width, mb_height; @@ -583,8 +587,10 @@ int rockchip_vpu2_vp8_dec_run(struct hantro_ctx *ctx) cfg_qp(ctx, hdr); cfg_parts(ctx, hdr); cfg_tap(ctx, hdr); - cfg_ref(ctx, hdr); - cfg_buffers(ctx, hdr); + + vb2_dst = hantro_get_dst_buf(ctx); + cfg_ref(ctx, hdr, vb2_dst); + cfg_buffers(ctx, hdr, vb2_dst); hantro_end_prepare_run(ctx); diff --git a/drivers/staging/media/hantro/rockchip_vpu_hw.c b/drivers/staging/media/hantro/rockchip_vpu_hw.c index 3ccc16413f42..d4f52957cc53 100644 --- a/drivers/staging/media/hantro/rockchip_vpu_hw.c +++ b/drivers/staging/media/hantro/rockchip_vpu_hw.c @@ -163,6 +163,19 @@ static const struct hantro_fmt rk3399_vpu_dec_fmts[] = { .codec_mode = HANTRO_MODE_NONE, }, { + .fourcc = V4L2_PIX_FMT_H264_SLICE, + .codec_mode = HANTRO_MODE_H264_DEC, + .max_depth = 2, + .frmsize = { + .min_width = 48, + .max_width = 1920, + .step_width = MB_DIM, + .min_height = 48, + .max_height = 1088, + .step_height = MB_DIM, + }, + }, + { .fourcc = V4L2_PIX_FMT_MPEG2_SLICE, .codec_mode = HANTRO_MODE_MPEG2_DEC, .max_depth = 2, @@ -388,6 +401,12 @@ static const struct hantro_codec_ops rk3399_vpu_codec_ops[] = { .init = hantro_jpeg_enc_init, .exit = hantro_jpeg_enc_exit, }, + [HANTRO_MODE_H264_DEC] = { + .run = rockchip_vpu2_h264_dec_run, + .reset = rockchip_vpu2_dec_reset, + .init = hantro_h264_dec_init, + .exit = hantro_h264_dec_exit, + }, [HANTRO_MODE_MPEG2_DEC] = { .run = rockchip_vpu2_mpeg2_dec_run, .reset = rockchip_vpu2_dec_reset, @@ -433,6 +452,8 @@ static const char * const rockchip_vpu_clk_names[] = { "aclk", "hclk" }; +/* VDPU1/VEPU1 */ + const struct hantro_variant rk3036_vpu_variant = { .dec_offset = 0x400, .dec_fmts = rk3066_vpu_dec_fmts, @@ -495,11 +516,14 @@ const struct hantro_variant rk3288_vpu_variant = { .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names) }; +/* VDPU2/VEPU2 */ + const struct hantro_variant rk3328_vpu_variant = { .dec_offset = 0x400, .dec_fmts = rk3399_vpu_dec_fmts, .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts), - .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER, + .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | + HANTRO_H264_DECODER, .codec_ops = rk3399_vpu_codec_ops, .irqs = rockchip_vdpu2_irqs, .num_irqs = ARRAY_SIZE(rockchip_vdpu2_irqs), @@ -524,3 +548,20 @@ const struct hantro_variant rk3399_vpu_variant = { .clk_names = rockchip_vpu_clk_names, .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names) }; + +const struct hantro_variant px30_vpu_variant = { + .enc_offset = 0x0, + .enc_fmts = rockchip_vpu_enc_fmts, + .num_enc_fmts = ARRAY_SIZE(rockchip_vpu_enc_fmts), + .dec_offset = 0x400, + .dec_fmts = rk3399_vpu_dec_fmts, + .num_dec_fmts = ARRAY_SIZE(rk3399_vpu_dec_fmts), + .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER | + HANTRO_VP8_DECODER | HANTRO_H264_DECODER, + .codec_ops = rk3399_vpu_codec_ops, + .irqs = rockchip_vpu2_irqs, + .num_irqs = ARRAY_SIZE(rockchip_vpu2_irqs), + .init = rk3036_vpu_hw_init, + .clk_names = rockchip_vpu_clk_names, + .num_clocks = ARRAY_SIZE(rockchip_vpu_clk_names) +}; diff --git a/drivers/staging/media/hantro/sama5d4_vdec_hw.c b/drivers/staging/media/hantro/sama5d4_vdec_hw.c index 58ae72c2b723..9c3b8cd0b239 100644 --- a/drivers/staging/media/hantro/sama5d4_vdec_hw.c +++ b/drivers/staging/media/hantro/sama5d4_vdec_hw.c @@ -64,11 +64,6 @@ static const struct hantro_fmt sama5d4_vdec_fmts[] = { }, }; -static int sama5d4_hw_init(struct hantro_dev *vpu) -{ - return 0; -} - /* * Supported codec ops. */ @@ -109,7 +104,6 @@ const struct hantro_variant sama5d4_vdec_variant = { .codec = HANTRO_MPEG2_DECODER | HANTRO_VP8_DECODER | HANTRO_H264_DECODER, .codec_ops = sama5d4_vdec_codec_ops, - .init = sama5d4_hw_init, .irqs = sama5d4_irqs, .num_irqs = ARRAY_SIZE(sama5d4_irqs), .clk_names = sama5d4_clk_names, diff --git a/drivers/staging/media/imx/Makefile b/drivers/staging/media/imx/Makefile index 6ac33275cc97..19c2fc54d424 100644 --- a/drivers/staging/media/imx/Makefile +++ b/drivers/staging/media/imx/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-mipi-csis.o +obj-$(CONFIG_VIDEO_IMX7_CSI) += imx8mq-mipi-csi2.o diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index 894c4de31790..127183732912 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -361,6 +361,7 @@ static void imx7_csi_dma_unsetup_vb2_buf(struct imx7_csi *csi, vb->timestamp = ktime_get_ns(); vb2_buffer_done(vb, return_status); + csi->active_vb2_buf[i] = NULL; } } } @@ -386,9 +387,10 @@ static int imx7_csi_dma_setup(struct imx7_csi *csi) return 0; } -static void imx7_csi_dma_cleanup(struct imx7_csi *csi) +static void imx7_csi_dma_cleanup(struct imx7_csi *csi, + enum vb2_buffer_state return_status) { - imx7_csi_dma_unsetup_vb2_buf(csi, VB2_BUF_STATE_ERROR); + imx7_csi_dma_unsetup_vb2_buf(csi, return_status); imx_media_free_dma_buf(csi->dev, &csi->underrun_buf); } @@ -421,6 +423,7 @@ static void imx7_csi_configure(struct imx7_csi *csi) struct v4l2_pix_format *out_pix = &vdev->fmt; int width = out_pix->width; u32 stride = 0; + u32 cr3 = BIT_FRMCNT_RST; u32 cr1, cr18; cr18 = imx7_csi_reg_read(csi, CSI_CSICR18); @@ -464,6 +467,7 @@ static void imx7_csi_configure(struct imx7_csi *csi) case MEDIA_BUS_FMT_SGBRG10_1X10: case MEDIA_BUS_FMT_SGRBG10_1X10: case MEDIA_BUS_FMT_SRGGB10_1X10: + cr3 |= BIT_TWO_8BIT_SENSOR; cr18 |= BIT_MIPI_DATA_FORMAT_RAW10; break; case MEDIA_BUS_FMT_Y12_1X12: @@ -471,6 +475,7 @@ static void imx7_csi_configure(struct imx7_csi *csi) case MEDIA_BUS_FMT_SGBRG12_1X12: case MEDIA_BUS_FMT_SGRBG12_1X12: case MEDIA_BUS_FMT_SRGGB12_1X12: + cr3 |= BIT_TWO_8BIT_SENSOR; cr18 |= BIT_MIPI_DATA_FORMAT_RAW12; break; case MEDIA_BUS_FMT_Y14_1X14: @@ -478,6 +483,7 @@ static void imx7_csi_configure(struct imx7_csi *csi) case MEDIA_BUS_FMT_SGBRG14_1X14: case MEDIA_BUS_FMT_SGRBG14_1X14: case MEDIA_BUS_FMT_SRGGB14_1X14: + cr3 |= BIT_TWO_8BIT_SENSOR; cr18 |= BIT_MIPI_DATA_FORMAT_RAW14; break; /* @@ -491,26 +497,11 @@ static void imx7_csi_configure(struct imx7_csi *csi) cr18 |= BIT_MIPI_DATA_FORMAT_YUV422_8B; break; } - - switch (out_pix->pixelformat) { - case V4L2_PIX_FMT_Y10: - case V4L2_PIX_FMT_Y12: - case V4L2_PIX_FMT_SBGGR8: - case V4L2_PIX_FMT_SGBRG8: - case V4L2_PIX_FMT_SGRBG8: - case V4L2_PIX_FMT_SRGGB8: - case V4L2_PIX_FMT_SBGGR16: - case V4L2_PIX_FMT_SGBRG16: - case V4L2_PIX_FMT_SGRBG16: - case V4L2_PIX_FMT_SRGGB16: - cr1 |= BIT_PIXEL_BIT; - break; - } } imx7_csi_reg_write(csi, cr1, CSI_CSICR1); imx7_csi_reg_write(csi, BIT_DMA_BURST_TYPE_RFF_INCR16, CSI_CSICR2); - imx7_csi_reg_write(csi, BIT_FRMCNT_RST, CSI_CSICR3); + imx7_csi_reg_write(csi, cr3, CSI_CSICR3); imx7_csi_reg_write(csi, cr18, CSI_CSICR18); imx7_csi_reg_write(csi, (width * out_pix->height) >> 2, CSI_CSIRXCNT); @@ -537,9 +528,10 @@ static int imx7_csi_init(struct imx7_csi *csi) return 0; } -static void imx7_csi_deinit(struct imx7_csi *csi) +static void imx7_csi_deinit(struct imx7_csi *csi, + enum vb2_buffer_state return_status) { - imx7_csi_dma_cleanup(csi); + imx7_csi_dma_cleanup(csi, return_status); imx7_csi_init_default(csi); imx7_csi_dmareq_rff_disable(csi); clk_disable_unprepare(csi->mclk); @@ -702,7 +694,7 @@ static int imx7_csi_s_stream(struct v4l2_subdev *sd, int enable) ret = v4l2_subdev_call(csi->src_sd, video, s_stream, 1); if (ret < 0) { - imx7_csi_deinit(csi); + imx7_csi_deinit(csi, VB2_BUF_STATE_QUEUED); goto out_unlock; } @@ -712,7 +704,7 @@ static int imx7_csi_s_stream(struct v4l2_subdev *sd, int enable) v4l2_subdev_call(csi->src_sd, video, s_stream, 0); - imx7_csi_deinit(csi); + imx7_csi_deinit(csi, VB2_BUF_STATE_ERROR); } csi->is_streaming = !!enable; diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c index ead696eb4610..41e33535de55 100644 --- a/drivers/staging/media/imx/imx7-mipi-csis.c +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -1019,10 +1019,8 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd, case 6: align = 2; break; - case 1: - case 3: - case 5: - case 7: + default: + /* 1, 3, 5, 7 */ align = 3; break; } diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c new file mode 100644 index 000000000000..a6f562009b9a --- /dev/null +++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c @@ -0,0 +1,991 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * NXP i.MX8MQ SoC series MIPI-CSI2 receiver driver + * + * Copyright (C) 2021 Purism SPC + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/interconnect.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/reset.h> +#include <linux/spinlock.h> + +#include <media/v4l2-common.h> +#include <media/v4l2-device.h> +#include <media/v4l2-fwnode.h> +#include <media/v4l2-mc.h> +#include <media/v4l2-subdev.h> + +#define MIPI_CSI2_DRIVER_NAME "imx8mq-mipi-csi2" +#define MIPI_CSI2_SUBDEV_NAME MIPI_CSI2_DRIVER_NAME + +#define MIPI_CSI2_PAD_SINK 0 +#define MIPI_CSI2_PAD_SOURCE 1 +#define MIPI_CSI2_PADS_NUM 2 + +#define MIPI_CSI2_DEF_PIX_WIDTH 640 +#define MIPI_CSI2_DEF_PIX_HEIGHT 480 + +/* Register map definition */ + +/* i.MX8MQ CSI-2 controller CSR */ +#define CSI2RX_CFG_NUM_LANES 0x100 +#define CSI2RX_CFG_DISABLE_DATA_LANES 0x104 +#define CSI2RX_BIT_ERR 0x108 +#define CSI2RX_IRQ_STATUS 0x10c +#define CSI2RX_IRQ_MASK 0x110 +#define CSI2RX_IRQ_MASK_ALL 0x1ff +#define CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE 0x8 +#define CSI2RX_ULPS_STATUS 0x114 +#define CSI2RX_PPI_ERRSOT_HS 0x118 +#define CSI2RX_PPI_ERRSOTSYNC_HS 0x11c +#define CSI2RX_PPI_ERRESC 0x120 +#define CSI2RX_PPI_ERRSYNCESC 0x124 +#define CSI2RX_PPI_ERRCONTROL 0x128 +#define CSI2RX_CFG_DISABLE_PAYLOAD_0 0x12c +#define CSI2RX_CFG_VID_VC_IGNORE 0x180 +#define CSI2RX_CFG_VID_VC 0x184 +#define CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL 0x188 +#define CSI2RX_CFG_DISABLE_PAYLOAD_1 0x130 + +enum { + ST_POWERED = 1, + ST_STREAMING = 2, + ST_SUSPENDED = 4, +}; + +enum imx8mq_mipi_csi_clk { + CSI2_CLK_CORE, + CSI2_CLK_ESC, + CSI2_CLK_UI, + CSI2_NUM_CLKS, +}; + +static const char * const imx8mq_mipi_csi_clk_id[CSI2_NUM_CLKS] = { + [CSI2_CLK_CORE] = "core", + [CSI2_CLK_ESC] = "esc", + [CSI2_CLK_UI] = "ui", +}; + +#define CSI2_NUM_CLKS ARRAY_SIZE(imx8mq_mipi_csi_clk_id) + +#define GPR_CSI2_1_RX_ENABLE BIT(13) +#define GPR_CSI2_1_VID_INTFC_ENB BIT(12) +#define GPR_CSI2_1_HSEL BIT(10) +#define GPR_CSI2_1_CONT_CLK_MODE BIT(8) +#define GPR_CSI2_1_S_PRG_RXHS_SETTLE(x) (((x) & 0x3f) << 2) + +/* + * The send level configures the number of entries that must accumulate in + * the Pixel FIFO before the data will be transferred to the video output. + * The exact value needed for this configuration is dependent on the rate at + * which the sensor transfers data to the CSI-2 Controller and the user + * video clock. + * + * The calculation is the classical rate-in rate-out type of problem: If the + * video bandwidth is 10% faster than the incoming mipi data and the video + * line length is 500 pixels, then the fifo should be allowed to fill + * 10% of the line length or 50 pixels. If the gap data is ok, then the level + * can be set to 16 and ignored. + */ +#define CSI2RX_SEND_LEVEL 64 + +struct csi_state { + struct device *dev; + void __iomem *regs; + struct clk_bulk_data clks[CSI2_NUM_CLKS]; + struct reset_control *rst; + struct regulator *mipi_phy_regulator; + + struct v4l2_subdev sd; + struct media_pad pads[MIPI_CSI2_PADS_NUM]; + struct v4l2_async_notifier notifier; + struct v4l2_subdev *src_sd; + + struct v4l2_fwnode_bus_mipi_csi2 bus; + + struct mutex lock; /* Protect csi2_fmt, format_mbus, state, hs_settle */ + const struct csi2_pix_format *csi2_fmt; + struct v4l2_mbus_framefmt format_mbus[MIPI_CSI2_PADS_NUM]; + u32 state; + u32 hs_settle; + + struct regmap *phy_gpr; + u8 phy_gpr_reg; + + struct icc_path *icc_path; + s32 icc_path_bw; +}; + +/* ----------------------------------------------------------------------------- + * Format helpers + */ + +struct csi2_pix_format { + u32 code; + u8 width; +}; + +static const struct csi2_pix_format imx8mq_mipi_csi_formats[] = { + /* RAW (Bayer and greyscale) formats. */ + { + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .width = 8, + }, { + .code = MEDIA_BUS_FMT_SGBRG8_1X8, + .width = 8, + }, { + .code = MEDIA_BUS_FMT_SGRBG8_1X8, + .width = 8, + }, { + .code = MEDIA_BUS_FMT_SRGGB8_1X8, + .width = 8, + }, { + .code = MEDIA_BUS_FMT_Y8_1X8, + .width = 8, + }, { + .code = MEDIA_BUS_FMT_SBGGR10_1X10, + .width = 10, + }, { + .code = MEDIA_BUS_FMT_SGBRG10_1X10, + .width = 10, + }, { + .code = MEDIA_BUS_FMT_SGRBG10_1X10, + .width = 10, + }, { + .code = MEDIA_BUS_FMT_SRGGB10_1X10, + .width = 10, + }, { + .code = MEDIA_BUS_FMT_Y10_1X10, + .width = 10, + }, { + .code = MEDIA_BUS_FMT_SBGGR12_1X12, + .width = 12, + }, { + .code = MEDIA_BUS_FMT_SGBRG12_1X12, + .width = 12, + }, { + .code = MEDIA_BUS_FMT_SGRBG12_1X12, + .width = 12, + }, { + .code = MEDIA_BUS_FMT_SRGGB12_1X12, + .width = 12, + }, { + .code = MEDIA_BUS_FMT_Y12_1X12, + .width = 12, + }, { + .code = MEDIA_BUS_FMT_SBGGR14_1X14, + .width = 14, + }, { + .code = MEDIA_BUS_FMT_SGBRG14_1X14, + .width = 14, + }, { + .code = MEDIA_BUS_FMT_SGRBG14_1X14, + .width = 14, + }, { + .code = MEDIA_BUS_FMT_SRGGB14_1X14, + .width = 14, + }, { + /* YUV formats */ + .code = MEDIA_BUS_FMT_YUYV8_2X8, + .width = 16, + }, { + .code = MEDIA_BUS_FMT_YUYV8_1X16, + .width = 16, + } +}; + +static const struct csi2_pix_format *find_csi2_format(u32 code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(imx8mq_mipi_csi_formats); i++) + if (code == imx8mq_mipi_csi_formats[i].code) + return &imx8mq_mipi_csi_formats[i]; + return NULL; +} + +/* ----------------------------------------------------------------------------- + * Hardware configuration + */ + +static inline void imx8mq_mipi_csi_write(struct csi_state *state, u32 reg, u32 val) +{ + writel(val, state->regs + reg); +} + +static int imx8mq_mipi_csi_sw_reset(struct csi_state *state) +{ + int ret; + + /* + * these are most likely self-clearing reset bits. to make it + * more clear, the reset-imx7 driver should implement the + * .reset() operation. + */ + ret = reset_control_assert(state->rst); + if (ret < 0) { + dev_err(state->dev, "Failed to assert resets: %d\n", ret); + return ret; + } + + return 0; +} + +static void imx8mq_mipi_csi_system_enable(struct csi_state *state, int on) +{ + if (!on) { + imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, 0xf); + return; + } + + regmap_update_bits(state->phy_gpr, + state->phy_gpr_reg, + 0x3fff, + GPR_CSI2_1_RX_ENABLE | + GPR_CSI2_1_VID_INTFC_ENB | + GPR_CSI2_1_HSEL | + GPR_CSI2_1_CONT_CLK_MODE | + GPR_CSI2_1_S_PRG_RXHS_SETTLE(state->hs_settle)); +} + +static void imx8mq_mipi_csi_set_params(struct csi_state *state) +{ + int lanes = state->bus.num_data_lanes; + + imx8mq_mipi_csi_write(state, CSI2RX_CFG_NUM_LANES, lanes - 1); + imx8mq_mipi_csi_write(state, CSI2RX_CFG_DISABLE_DATA_LANES, + (0xf << lanes) & 0xf); + imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK, CSI2RX_IRQ_MASK_ALL); + /* + * 0x180 bit 0 controls the Virtual Channel behaviour: when set the + * interface ignores the Virtual Channel (VC) field in received packets; + * when cleared it causes the interface to only accept packets whose VC + * matches the value to which VC is set at offset 0x184. + */ + imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_VC_IGNORE, 1); + imx8mq_mipi_csi_write(state, CSI2RX_CFG_VID_P_FIFO_SEND_LEVEL, + CSI2RX_SEND_LEVEL); +} + +static int imx8mq_mipi_csi_clk_enable(struct csi_state *state) +{ + return clk_bulk_prepare_enable(CSI2_NUM_CLKS, state->clks); +} + +static void imx8mq_mipi_csi_clk_disable(struct csi_state *state) +{ + clk_bulk_disable_unprepare(CSI2_NUM_CLKS, state->clks); +} + +static int imx8mq_mipi_csi_clk_get(struct csi_state *state) +{ + unsigned int i; + + for (i = 0; i < CSI2_NUM_CLKS; i++) + state->clks[i].id = imx8mq_mipi_csi_clk_id[i]; + + return devm_clk_bulk_get(state->dev, CSI2_NUM_CLKS, state->clks); +} + +static int imx8mq_mipi_csi_calc_hs_settle(struct csi_state *state) +{ + s64 link_freq; + u32 lane_rate; + unsigned long esc_clk_rate; + u32 min_ths_settle, max_ths_settle, ths_settle_ns, esc_clk_period_ns; + + /* Calculate the line rate from the pixel rate. */ + link_freq = v4l2_get_link_freq(state->src_sd->ctrl_handler, + state->csi2_fmt->width, + state->bus.num_data_lanes * 2); + if (link_freq < 0) { + dev_err(state->dev, "Unable to obtain link frequency: %d\n", + (int)link_freq); + return link_freq; + } + + lane_rate = link_freq * 2; + if (lane_rate < 80000000 || lane_rate > 1500000000) { + dev_dbg(state->dev, "Out-of-bound lane rate %u\n", lane_rate); + return -EINVAL; + } + + /* + * The D-PHY specification requires Ths-settle to be in the range + * 85ns + 6*UI to 140ns + 10*UI, with the unit interval UI being half + * the clock period. + * + * The Ths-settle value is expressed in the hardware as a multiple of + * the Esc clock period: + * + * Ths-settle = (PRG_RXHS_SETTLE + 1) * Tperiod of RxClkInEsc + * + * Due to the one cycle inaccuracy introduced by rounding, the + * documentation recommends picking a value away from the boundaries. + * Let's pick the average. + */ + esc_clk_rate = clk_get_rate(state->clks[CSI2_CLK_ESC].clk); + if (!esc_clk_rate) { + dev_err(state->dev, "Could not get esc clock rate.\n"); + return -EINVAL; + } + + dev_dbg(state->dev, "esc clk rate: %lu\n", esc_clk_rate); + esc_clk_period_ns = 1000000000 / esc_clk_rate; + + min_ths_settle = 85 + 6 * 1000000 / (lane_rate / 1000); + max_ths_settle = 140 + 10 * 1000000 / (lane_rate / 1000); + ths_settle_ns = (min_ths_settle + max_ths_settle) / 2; + + state->hs_settle = ths_settle_ns / esc_clk_period_ns - 1; + + dev_dbg(state->dev, "lane rate %u Ths_settle %u hs_settle %u\n", + lane_rate, ths_settle_ns, state->hs_settle); + + return 0; +} + +static int imx8mq_mipi_csi_start_stream(struct csi_state *state) +{ + int ret; + + ret = imx8mq_mipi_csi_sw_reset(state); + if (ret) + return ret; + + imx8mq_mipi_csi_set_params(state); + ret = imx8mq_mipi_csi_calc_hs_settle(state); + if (ret) + return ret; + + imx8mq_mipi_csi_system_enable(state, true); + + return 0; +} + +static void imx8mq_mipi_csi_stop_stream(struct csi_state *state) +{ + imx8mq_mipi_csi_system_enable(state, false); +} + +/* ----------------------------------------------------------------------------- + * V4L2 subdev operations + */ + +static struct csi_state *mipi_sd_to_csi2_state(struct v4l2_subdev *sdev) +{ + return container_of(sdev, struct csi_state, sd); +} + +static int imx8mq_mipi_csi_s_stream(struct v4l2_subdev *sd, int enable) +{ + struct csi_state *state = mipi_sd_to_csi2_state(sd); + int ret = 0; + + imx8mq_mipi_csi_write(state, CSI2RX_IRQ_MASK, + CSI2RX_IRQ_MASK_ULPS_STATUS_CHANGE); + + if (enable) { + ret = pm_runtime_resume_and_get(state->dev); + if (ret < 0) + return ret; + } + + mutex_lock(&state->lock); + + if (enable) { + if (state->state & ST_SUSPENDED) { + ret = -EBUSY; + goto unlock; + } + + ret = imx8mq_mipi_csi_start_stream(state); + if (ret < 0) + goto unlock; + + ret = v4l2_subdev_call(state->src_sd, video, s_stream, 1); + if (ret < 0) + goto unlock; + + state->state |= ST_STREAMING; + } else { + v4l2_subdev_call(state->src_sd, video, s_stream, 0); + imx8mq_mipi_csi_stop_stream(state); + state->state &= ~ST_STREAMING; + } + +unlock: + mutex_unlock(&state->lock); + + if (!enable || ret < 0) + pm_runtime_put(state->dev); + + return ret; +} + +static struct v4l2_mbus_framefmt * +imx8mq_mipi_csi_get_format(struct csi_state *state, + struct v4l2_subdev_state *sd_state, + enum v4l2_subdev_format_whence which, + unsigned int pad) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_get_try_format(&state->sd, sd_state, pad); + + return &state->format_mbus[pad]; +} + +static int imx8mq_mipi_csi_init_cfg(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state) +{ + struct csi_state *state = mipi_sd_to_csi2_state(sd); + struct v4l2_mbus_framefmt *fmt_sink; + struct v4l2_mbus_framefmt *fmt_source; + enum v4l2_subdev_format_whence which; + + which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; + fmt_sink = imx8mq_mipi_csi_get_format(state, sd_state, which, + MIPI_CSI2_PAD_SINK); + + fmt_sink->code = MEDIA_BUS_FMT_SGBRG10_1X10; + fmt_sink->width = MIPI_CSI2_DEF_PIX_WIDTH; + fmt_sink->height = MIPI_CSI2_DEF_PIX_HEIGHT; + fmt_sink->field = V4L2_FIELD_NONE; + + fmt_sink->colorspace = V4L2_COLORSPACE_RAW; + fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace); + fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace); + fmt_sink->quantization = + V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace, + fmt_sink->ycbcr_enc); + + fmt_source = imx8mq_mipi_csi_get_format(state, sd_state, which, + MIPI_CSI2_PAD_SOURCE); + *fmt_source = *fmt_sink; + + return 0; +} + +static int imx8mq_mipi_csi_get_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *sdformat) +{ + struct csi_state *state = mipi_sd_to_csi2_state(sd); + struct v4l2_mbus_framefmt *fmt; + + fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which, + sdformat->pad); + + mutex_lock(&state->lock); + + sdformat->format = *fmt; + + mutex_unlock(&state->lock); + + return 0; +} + +static int imx8mq_mipi_csi_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct csi_state *state = mipi_sd_to_csi2_state(sd); + + /* + * We can't transcode in any way, the source format is identical + * to the sink format. + */ + if (code->pad == MIPI_CSI2_PAD_SOURCE) { + struct v4l2_mbus_framefmt *fmt; + + if (code->index > 0) + return -EINVAL; + + fmt = imx8mq_mipi_csi_get_format(state, sd_state, code->which, + code->pad); + code->code = fmt->code; + return 0; + } + + if (code->pad != MIPI_CSI2_PAD_SINK) + return -EINVAL; + + if (code->index >= ARRAY_SIZE(imx8mq_mipi_csi_formats)) + return -EINVAL; + + code->code = imx8mq_mipi_csi_formats[code->index].code; + + return 0; +} + +static int imx8mq_mipi_csi_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *sdformat) +{ + struct csi_state *state = mipi_sd_to_csi2_state(sd); + struct csi2_pix_format const *csi2_fmt; + struct v4l2_mbus_framefmt *fmt; + + /* + * The device can't transcode in any way, the source format can't be + * modified. + */ + if (sdformat->pad == MIPI_CSI2_PAD_SOURCE) + return imx8mq_mipi_csi_get_fmt(sd, sd_state, sdformat); + + if (sdformat->pad != MIPI_CSI2_PAD_SINK) + return -EINVAL; + + csi2_fmt = find_csi2_format(sdformat->format.code); + if (!csi2_fmt) + csi2_fmt = &imx8mq_mipi_csi_formats[0]; + + fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which, + sdformat->pad); + + mutex_lock(&state->lock); + + fmt->code = csi2_fmt->code; + fmt->width = sdformat->format.width; + fmt->height = sdformat->format.height; + + sdformat->format = *fmt; + + /* Propagate the format from sink to source. */ + fmt = imx8mq_mipi_csi_get_format(state, sd_state, sdformat->which, + MIPI_CSI2_PAD_SOURCE); + *fmt = sdformat->format; + + /* Store the CSI2 format descriptor for active formats. */ + if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE) + state->csi2_fmt = csi2_fmt; + + mutex_unlock(&state->lock); + + return 0; +} + +static const struct v4l2_subdev_video_ops imx8mq_mipi_csi_video_ops = { + .s_stream = imx8mq_mipi_csi_s_stream, +}; + +static const struct v4l2_subdev_pad_ops imx8mq_mipi_csi_pad_ops = { + .init_cfg = imx8mq_mipi_csi_init_cfg, + .enum_mbus_code = imx8mq_mipi_csi_enum_mbus_code, + .get_fmt = imx8mq_mipi_csi_get_fmt, + .set_fmt = imx8mq_mipi_csi_set_fmt, +}; + +static const struct v4l2_subdev_ops imx8mq_mipi_csi_subdev_ops = { + .video = &imx8mq_mipi_csi_video_ops, + .pad = &imx8mq_mipi_csi_pad_ops, +}; + +/* ----------------------------------------------------------------------------- + * Media entity operations + */ + +static const struct media_entity_operations imx8mq_mipi_csi_entity_ops = { + .link_validate = v4l2_subdev_link_validate, + .get_fwnode_pad = v4l2_subdev_get_fwnode_pad_1_to_1, +}; + +/* ----------------------------------------------------------------------------- + * Async subdev notifier + */ + +static struct csi_state * +mipi_notifier_to_csi2_state(struct v4l2_async_notifier *n) +{ + return container_of(n, struct csi_state, notifier); +} + +static int imx8mq_mipi_csi_notify_bound(struct v4l2_async_notifier *notifier, + struct v4l2_subdev *sd, + struct v4l2_async_subdev *asd) +{ + struct csi_state *state = mipi_notifier_to_csi2_state(notifier); + struct media_pad *sink = &state->sd.entity.pads[MIPI_CSI2_PAD_SINK]; + + state->src_sd = sd; + + return v4l2_create_fwnode_links_to_pad(sd, sink, MEDIA_LNK_FL_ENABLED | + MEDIA_LNK_FL_IMMUTABLE); +} + +static const struct v4l2_async_notifier_operations imx8mq_mipi_csi_notify_ops = { + .bound = imx8mq_mipi_csi_notify_bound, +}; + +static int imx8mq_mipi_csi_async_register(struct csi_state *state) +{ + struct v4l2_fwnode_endpoint vep = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + struct v4l2_async_subdev *asd; + struct fwnode_handle *ep; + unsigned int i; + int ret; + + v4l2_async_notifier_init(&state->notifier); + + ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(state->dev), 0, 0, + FWNODE_GRAPH_ENDPOINT_NEXT); + if (!ep) + return -ENOTCONN; + + ret = v4l2_fwnode_endpoint_parse(ep, &vep); + if (ret) + goto err_parse; + + for (i = 0; i < vep.bus.mipi_csi2.num_data_lanes; ++i) { + if (vep.bus.mipi_csi2.data_lanes[i] != i + 1) { + dev_err(state->dev, + "data lanes reordering is not supported"); + ret = -EINVAL; + goto err_parse; + } + } + + state->bus = vep.bus.mipi_csi2; + + dev_dbg(state->dev, "data lanes: %d flags: 0x%08x\n", + state->bus.num_data_lanes, + state->bus.flags); + + asd = v4l2_async_notifier_add_fwnode_remote_subdev(&state->notifier, + ep, struct v4l2_async_subdev); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); + goto err_parse; + } + + fwnode_handle_put(ep); + + state->notifier.ops = &imx8mq_mipi_csi_notify_ops; + + ret = v4l2_async_subdev_notifier_register(&state->sd, &state->notifier); + if (ret) + return ret; + + return v4l2_async_register_subdev(&state->sd); + +err_parse: + fwnode_handle_put(ep); + + return ret; +} + +/* ----------------------------------------------------------------------------- + * Suspend/resume + */ + +static int imx8mq_mipi_csi_pm_suspend(struct device *dev, bool runtime) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + int ret = 0; + + mutex_lock(&state->lock); + + if (state->state & ST_POWERED) { + imx8mq_mipi_csi_stop_stream(state); + imx8mq_mipi_csi_clk_disable(state); + state->state &= ~ST_POWERED; + if (!runtime) + state->state |= ST_SUSPENDED; + } + + mutex_unlock(&state->lock); + + ret = icc_set_bw(state->icc_path, 0, 0); + if (ret) + dev_err(dev, "icc_set_bw failed with %d\n", ret); + + return ret ? -EAGAIN : 0; +} + +static int imx8mq_mipi_csi_pm_resume(struct device *dev, bool runtime) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + int ret = 0; + + ret = icc_set_bw(state->icc_path, 0, state->icc_path_bw); + if (ret) { + dev_err(dev, "icc_set_bw failed with %d\n", ret); + return ret; + } + + mutex_lock(&state->lock); + + if (!runtime && !(state->state & ST_SUSPENDED)) + goto unlock; + + if (!(state->state & ST_POWERED)) { + state->state |= ST_POWERED; + ret = imx8mq_mipi_csi_clk_enable(state); + } + if (state->state & ST_STREAMING) { + ret = imx8mq_mipi_csi_start_stream(state); + if (ret) + goto unlock; + } + + state->state &= ~ST_SUSPENDED; + +unlock: + mutex_unlock(&state->lock); + + return ret ? -EAGAIN : 0; +} + +static int __maybe_unused imx8mq_mipi_csi_suspend(struct device *dev) +{ + return imx8mq_mipi_csi_pm_suspend(dev, false); +} + +static int __maybe_unused imx8mq_mipi_csi_resume(struct device *dev) +{ + return imx8mq_mipi_csi_pm_resume(dev, false); +} + +static int __maybe_unused imx8mq_mipi_csi_runtime_suspend(struct device *dev) +{ + return imx8mq_mipi_csi_pm_suspend(dev, true); +} + +static int __maybe_unused imx8mq_mipi_csi_runtime_resume(struct device *dev) +{ + return imx8mq_mipi_csi_pm_resume(dev, true); +} + +static const struct dev_pm_ops imx8mq_mipi_csi_pm_ops = { + SET_RUNTIME_PM_OPS(imx8mq_mipi_csi_runtime_suspend, + imx8mq_mipi_csi_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(imx8mq_mipi_csi_suspend, imx8mq_mipi_csi_resume) +}; + +/* ----------------------------------------------------------------------------- + * Probe/remove & platform driver + */ + +static int imx8mq_mipi_csi_subdev_init(struct csi_state *state) +{ + struct v4l2_subdev *sd = &state->sd; + + v4l2_subdev_init(sd, &imx8mq_mipi_csi_subdev_ops); + sd->owner = THIS_MODULE; + snprintf(sd->name, sizeof(sd->name), "%s %s", + MIPI_CSI2_SUBDEV_NAME, dev_name(state->dev)); + + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + + sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; + sd->entity.ops = &imx8mq_mipi_csi_entity_ops; + + sd->dev = state->dev; + + state->csi2_fmt = &imx8mq_mipi_csi_formats[0]; + imx8mq_mipi_csi_init_cfg(sd, NULL); + + state->pads[MIPI_CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK + | MEDIA_PAD_FL_MUST_CONNECT; + state->pads[MIPI_CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE + | MEDIA_PAD_FL_MUST_CONNECT; + return media_entity_pads_init(&sd->entity, MIPI_CSI2_PADS_NUM, + state->pads); +} + +static void imx8mq_mipi_csi_release_icc(struct platform_device *pdev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + + icc_put(state->icc_path); +} + +static int imx8mq_mipi_csi_init_icc(struct platform_device *pdev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(&pdev->dev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + + /* Optional interconnect request */ + state->icc_path = of_icc_get(&pdev->dev, "dram"); + if (IS_ERR_OR_NULL(state->icc_path)) + return PTR_ERR_OR_ZERO(state->icc_path); + + state->icc_path_bw = MBps_to_icc(700); + + return 0; +} + +static int imx8mq_mipi_csi_parse_dt(struct csi_state *state) +{ + struct device *dev = state->dev; + struct device_node *np = state->dev->of_node; + struct device_node *node; + phandle ph; + u32 out_val[2]; + int ret = 0; + + state->rst = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(state->rst)) { + dev_err(dev, "Failed to get reset: %pe\n", state->rst); + return PTR_ERR(state->rst); + } + + ret = of_property_read_u32_array(np, "fsl,mipi-phy-gpr", out_val, + ARRAY_SIZE(out_val)); + if (ret) { + dev_err(dev, "no fsl,mipi-phy-gpr property found: %d\n", ret); + return ret; + } + + ph = *out_val; + + node = of_find_node_by_phandle(ph); + if (!node) { + dev_err(dev, "Error finding node by phandle\n"); + return -ENODEV; + } + state->phy_gpr = syscon_node_to_regmap(node); + of_node_put(node); + if (IS_ERR(state->phy_gpr)) { + dev_err(dev, "failed to get gpr regmap: %pe\n", state->phy_gpr); + return PTR_ERR(state->phy_gpr); + } + + state->phy_gpr_reg = out_val[1]; + dev_dbg(dev, "phy gpr register set to 0x%x\n", state->phy_gpr_reg); + + return ret; +} + +static int imx8mq_mipi_csi_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct csi_state *state; + int ret; + + state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->dev = dev; + + ret = imx8mq_mipi_csi_parse_dt(state); + if (ret < 0) { + dev_err(dev, "Failed to parse device tree: %d\n", ret); + return ret; + } + + /* Acquire resources. */ + state->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(state->regs)) + return PTR_ERR(state->regs); + + ret = imx8mq_mipi_csi_clk_get(state); + if (ret < 0) + return ret; + + platform_set_drvdata(pdev, &state->sd); + + mutex_init(&state->lock); + + ret = imx8mq_mipi_csi_subdev_init(state); + if (ret < 0) + goto mutex; + + ret = imx8mq_mipi_csi_init_icc(pdev); + if (ret) + goto mutex; + + /* Enable runtime PM. */ + pm_runtime_enable(dev); + if (!pm_runtime_enabled(dev)) { + ret = imx8mq_mipi_csi_pm_resume(dev, true); + if (ret < 0) + goto icc; + } + + ret = imx8mq_mipi_csi_async_register(state); + if (ret < 0) + goto cleanup; + + return 0; + +cleanup: + pm_runtime_disable(&pdev->dev); + imx8mq_mipi_csi_pm_suspend(&pdev->dev, true); + + media_entity_cleanup(&state->sd.entity); + v4l2_async_notifier_unregister(&state->notifier); + v4l2_async_notifier_cleanup(&state->notifier); + v4l2_async_unregister_subdev(&state->sd); +icc: + imx8mq_mipi_csi_release_icc(pdev); +mutex: + mutex_destroy(&state->lock); + + return ret; +} + +static int imx8mq_mipi_csi_remove(struct platform_device *pdev) +{ + struct v4l2_subdev *sd = platform_get_drvdata(pdev); + struct csi_state *state = mipi_sd_to_csi2_state(sd); + + v4l2_async_notifier_unregister(&state->notifier); + v4l2_async_notifier_cleanup(&state->notifier); + v4l2_async_unregister_subdev(&state->sd); + + pm_runtime_disable(&pdev->dev); + imx8mq_mipi_csi_pm_suspend(&pdev->dev, true); + media_entity_cleanup(&state->sd.entity); + mutex_destroy(&state->lock); + pm_runtime_set_suspended(&pdev->dev); + imx8mq_mipi_csi_release_icc(pdev); + + return 0; +} + +static const struct of_device_id imx8mq_mipi_csi_of_match[] = { + { .compatible = "fsl,imx8mq-mipi-csi2", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, imx8mq_mipi_csi_of_match); + +static struct platform_driver imx8mq_mipi_csi_driver = { + .probe = imx8mq_mipi_csi_probe, + .remove = imx8mq_mipi_csi_remove, + .driver = { + .of_match_table = imx8mq_mipi_csi_of_match, + .name = MIPI_CSI2_DRIVER_NAME, + .pm = &imx8mq_mipi_csi_pm_ops, + }, +}; + +module_platform_driver(imx8mq_mipi_csi_driver); + +MODULE_DESCRIPTION("i.MX8MQ MIPI CSI-2 receiver driver"); +MODULE_AUTHOR("Martin Kepplinger <martin.kepplinger@puri.sm>"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:imx8mq-mipi-csi2"); diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c index 6821e3d05d34..ef0311a16d01 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c @@ -247,6 +247,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, const struct v4l2_ctrl_hevc_slice_params *slice_params; const struct v4l2_ctrl_hevc_decode_params *decode_params; const struct v4l2_hevc_pred_weight_table *pred_weight_table; + unsigned int width_in_ctb_luma, ctb_size_luma; + unsigned int log2_max_luma_coding_block_size; dma_addr_t src_buf_addr; dma_addr_t src_buf_end_addr; u32 chroma_log2_weight_denom; @@ -260,15 +262,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, decode_params = run->h265.decode_params; pred_weight_table = &slice_params->pred_weight_table; + log2_max_luma_coding_block_size = + sps->log2_min_luma_coding_block_size_minus3 + 3 + + sps->log2_diff_max_min_luma_coding_block_size; + ctb_size_luma = 1UL << log2_max_luma_coding_block_size; + width_in_ctb_luma = + DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); + /* MV column buffer size and allocation. */ if (!ctx->codec.h265.mv_col_buf_size) { unsigned int num_buffers = run->dst->vb2_buf.vb2_queue->num_buffers; - unsigned int log2_max_luma_coding_block_size = - sps->log2_min_luma_coding_block_size_minus3 + 3 + - sps->log2_diff_max_min_luma_coding_block_size; - unsigned int ctb_size_luma = - 1UL << log2_max_luma_coding_block_size; /* * Each CTB requires a MV col buffer with a specific unit size. @@ -322,15 +326,17 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr); cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); - /* Coding tree block address: start at the beginning. */ - reg = VE_DEC_H265_DEC_CTB_ADDR_X(0) | VE_DEC_H265_DEC_CTB_ADDR_Y(0); + /* Coding tree block address */ + reg = VE_DEC_H265_DEC_CTB_ADDR_X(slice_params->slice_segment_addr % width_in_ctb_luma); + reg |= VE_DEC_H265_DEC_CTB_ADDR_Y(slice_params->slice_segment_addr / width_in_ctb_luma); cedrus_write(dev, VE_DEC_H265_DEC_CTB_ADDR, reg); cedrus_write(dev, VE_DEC_H265_TILE_START_CTB, 0); cedrus_write(dev, VE_DEC_H265_TILE_END_CTB, 0); /* Clear the number of correctly-decoded coding tree blocks. */ - cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); + if (ctx->fh.m2m_ctx->new_frame) + cedrus_write(dev, VE_DEC_H265_DEC_CTB_NUM, 0); /* Initialize bitstream access. */ cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_INIT_SWDEC); @@ -482,8 +488,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT, slice_params->flags); - /* FIXME: For multi-slice support. */ - reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC; + if (ctx->fh.m2m_ctx->new_frame) + reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC; cedrus_write(dev, VE_DEC_H265_DEC_SLICE_HDR_INFO0, reg); diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c index 32c13ecb22d8..c589fe9dae70 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c @@ -340,6 +340,7 @@ static int cedrus_s_fmt_vid_out(struct file *file, void *priv, switch (ctx->src_fmt.pixelformat) { case V4L2_PIX_FMT_H264_SLICE: + case V4L2_PIX_FMT_HEVC_SLICE: vq->subsystem_flags |= VB2_V4L2_FL_SUPPORTS_M2M_HOLD_CAPTURE_BUF; break; diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c index 89709cd06d4d..d321790b07d9 100644 --- a/drivers/staging/media/tegra-video/vi.c +++ b/drivers/staging/media/tegra-video/vi.c @@ -508,8 +508,8 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan, return -ENODEV; sd_state = v4l2_subdev_alloc_state(subdev); - if (!sd_state) - return -ENOMEM; + if (IS_ERR(sd_state)) + return PTR_ERR(sd_state); /* * Retrieve the format information and if requested format isn't * supported, keep the current format. |