aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/media/atomisp/pci/atomisp2/atomisp_csi2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/media/atomisp/pci/atomisp2/atomisp_csi2.c')
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp2/atomisp_csi2.c442
1 files changed, 0 insertions, 442 deletions
diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_csi2.c b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_csi2.c
deleted file mode 100644
index fa03b78c3580..000000000000
--- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_csi2.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Support for Medifield PNW Camera Imaging ISP subsystem.
- *
- * Copyright (c) 2010 Intel Corporation. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- *
- */
-
-#include <media/v4l2-event.h>
-#include <media/v4l2-mediabus.h>
-#include "atomisp_cmd.h"
-#include "atomisp_internal.h"
-#include "atomisp-regs.h"
-
-static struct v4l2_mbus_framefmt *__csi2_get_format(struct
- atomisp_mipi_csi2_device
- *csi2,
- struct
- v4l2_subdev_pad_config *cfg,
- enum
- v4l2_subdev_format_whence
- which, unsigned int pad)
-{
- if (which == V4L2_SUBDEV_FORMAT_TRY)
- return v4l2_subdev_get_try_format(&csi2->subdev, cfg, pad);
- else
- return &csi2->formats[pad];
-}
-
-/*
- * csi2_enum_mbus_code - Handle pixel format enumeration
- * @sd : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
- * @code : pointer to v4l2_subdev_pad_mbus_code_enum structure
- * return -EINVAL or zero on success
-*/
-static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- const struct atomisp_in_fmt_conv *ic = atomisp_in_fmt_conv;
- unsigned int i = 0;
-
- while (ic->code) {
- if (i == code->index) {
- code->code = ic->code;
- return 0;
- }
- i++, ic++;
- }
-
- return -EINVAL;
-}
-
-/*
- * csi2_get_format - Handle get format by pads subdev method
- * @sd : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
- * @pad: pad num
- * @fmt: pointer to v4l2 format structure
- * return -EINVAL or zero on sucess
-*/
-static int csi2_get_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *format;
-
- format = __csi2_get_format(csi2, cfg, fmt->which, fmt->pad);
-
- fmt->format = *format;
-
- return 0;
-}
-
-int atomisp_csi2_set_ffmt(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- unsigned int which, uint16_t pad,
- struct v4l2_mbus_framefmt *ffmt)
-{
- struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
- struct v4l2_mbus_framefmt *actual_ffmt =
-#ifndef ISP2401
- __csi2_get_format(csi2, cfg, which, pad);
-#else
- __csi2_get_format(csi2, cfg, which, pad);
-#endif
-
- if (pad == CSI2_PAD_SINK) {
- const struct atomisp_in_fmt_conv *ic;
- struct v4l2_mbus_framefmt tmp_ffmt;
-
- ic = atomisp_find_in_fmt_conv(ffmt->code);
- if (ic)
- actual_ffmt->code = ic->code;
- else
- actual_ffmt->code = atomisp_in_fmt_conv[0].code;
-
- actual_ffmt->width = clamp_t(
- u32, ffmt->width, ATOM_ISP_MIN_WIDTH,
- ATOM_ISP_MAX_WIDTH);
- actual_ffmt->height = clamp_t(
- u32, ffmt->height, ATOM_ISP_MIN_HEIGHT,
- ATOM_ISP_MAX_HEIGHT);
-
- tmp_ffmt = *ffmt = *actual_ffmt;
-
- return atomisp_csi2_set_ffmt(sd, cfg, which, CSI2_PAD_SOURCE,
- &tmp_ffmt);
- }
-
- /* FIXME: DPCM decompression */
- *actual_ffmt = *ffmt =
-#ifndef ISP2401
- *__csi2_get_format(csi2, cfg, which, CSI2_PAD_SINK);
-#else
- *__csi2_get_format(csi2, cfg, which, CSI2_PAD_SINK);
-#endif
-
- return 0;
-}
-
-/*
- * csi2_set_format - Handle set format by pads subdev method
- * @sd : pointer to v4l2 subdev structure
- * @fh : V4L2 subdev file handle
- * @pad: pad num
- * @fmt: pointer to v4l2 format structure
- * return -EINVAL or zero on success
-*/
-static int csi2_set_format(struct v4l2_subdev *sd,
- struct v4l2_subdev_pad_config *cfg,
- struct v4l2_subdev_format *fmt)
-{
- return atomisp_csi2_set_ffmt(sd, cfg, fmt->which, fmt->pad,
- &fmt->format);
-}
-
-/*
- * csi2_set_stream - Enable/Disable streaming on the CSI2 module
- * @sd: ISP CSI2 V4L2 subdevice
- * @enable: Enable/disable stream (1/0)
- *
- * Return 0 on success or a negative error code otherwise.
-*/
-static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
-{
- return 0;
-}
-
-/* subdev core operations */
-static const struct v4l2_subdev_core_ops csi2_core_ops = {
-};
-
-/* subdev video operations */
-static const struct v4l2_subdev_video_ops csi2_video_ops = {
- .s_stream = csi2_set_stream,
-};
-
-/* subdev pad operations */
-static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
- .enum_mbus_code = csi2_enum_mbus_code,
- .get_fmt = csi2_get_format,
- .set_fmt = csi2_set_format,
- .link_validate = v4l2_subdev_link_validate_default,
-};
-
-/* subdev operations */
-static const struct v4l2_subdev_ops csi2_ops = {
- .core = &csi2_core_ops,
- .video = &csi2_video_ops,
- .pad = &csi2_pad_ops,
-};
-
-#ifndef ISP2401
-
-#endif
-/*
- * csi2_link_setup - Setup CSI2 connections.
- * @entity : Pointer to media entity structure
- * @local : Pointer to local pad array
- * @remote : Pointer to remote pad array
- * @flags : Link flags
- * return -EINVAL or zero on success
-*/
-static int csi2_link_setup(struct media_entity *entity,
- const struct media_pad *local,
- const struct media_pad *remote, u32 flags)
-{
- struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
- struct atomisp_mipi_csi2_device *csi2 = v4l2_get_subdevdata(sd);
- u32 result = local->index | is_media_entity_v4l2_subdev(remote->entity);
-
- switch (result) {
- case CSI2_PAD_SOURCE | MEDIA_ENT_F_OLD_BASE:
- /* not supported yet */
- return -EINVAL;
-
- case CSI2_PAD_SOURCE | MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN:
- if (flags & MEDIA_LNK_FL_ENABLED) {
- if (csi2->output & ~CSI2_OUTPUT_ISP_SUBDEV)
- return -EBUSY;
- csi2->output |= CSI2_OUTPUT_ISP_SUBDEV;
- } else {
- csi2->output &= ~CSI2_OUTPUT_ISP_SUBDEV;
- }
- break;
-
- default:
- /* Link from camera to CSI2 is fixed... */
- return -EINVAL;
- }
- return 0;
-}
-
-/* media operations */
-static const struct media_entity_operations csi2_media_ops = {
- .link_setup = csi2_link_setup,
- .link_validate = v4l2_subdev_link_validate,
-};
-
-/*
-* ispcsi2_init_entities - Initialize subdev and media entity.
-* @csi2: Pointer to ispcsi2 structure.
-* return -ENOMEM or zero on success
-*/
-static int mipi_csi2_init_entities(struct atomisp_mipi_csi2_device *csi2,
- int port)
-{
- struct v4l2_subdev *sd = &csi2->subdev;
- struct media_pad *pads = csi2->pads;
- struct media_entity *me = &sd->entity;
- int ret;
-
- v4l2_subdev_init(sd, &csi2_ops);
- snprintf(sd->name, sizeof(sd->name), "ATOM ISP CSI2-port%d", port);
-
- v4l2_set_subdevdata(sd, csi2);
- sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
-
- pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
- pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-
- me->ops = &csi2_media_ops;
- me->function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
- ret = media_entity_pads_init(me, CSI2_PADS_NUM, pads);
- if (ret < 0)
- return ret;
-
- csi2->formats[CSI2_PAD_SINK].code =
- csi2->formats[CSI2_PAD_SOURCE].code =
- atomisp_in_fmt_conv[0].code;
-
- return 0;
-}
-
-void
-atomisp_mipi_csi2_unregister_entities(struct atomisp_mipi_csi2_device *csi2)
-{
- media_entity_cleanup(&csi2->subdev.entity);
- v4l2_device_unregister_subdev(&csi2->subdev);
-}
-
-int atomisp_mipi_csi2_register_entities(struct atomisp_mipi_csi2_device *csi2,
- struct v4l2_device *vdev)
-{
- int ret;
-
- /* Register the subdev and video nodes. */
- ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
- if (ret < 0)
- goto error;
-
- return 0;
-
-error:
- atomisp_mipi_csi2_unregister_entities(csi2);
- return ret;
-}
-
-static const int LIMIT_SHIFT = 6; /* Limit numeric range into 31 bits */
-
-static int
-atomisp_csi2_configure_calc(const short int coeffs[2], int mipi_freq, int def)
-{
- /* Delay counter accuracy, 1/0.0625 for ANN/CHT, 1/0.125 for BXT */
- static const int accinv = 16; /* 1 / COUNT_ACC */
- int r;
-
- if (mipi_freq >> LIMIT_SHIFT <= 0)
- return def;
-
- r = accinv * coeffs[1] * (500000000 >> LIMIT_SHIFT);
- r /= mipi_freq >> LIMIT_SHIFT;
- r += accinv * coeffs[0];
-
- return r;
-}
-
-static void atomisp_csi2_configure_isp2401(struct atomisp_sub_device *asd)
-{
- /*
- * The ISP2401 new input system CSI2+ receiver has several
- * parameters affecting the receiver timings. These depend
- * on the MIPI bus frequency F in Hz (sensor transmitter rate)
- * as follows:
- * register value = (A/1e9 + B * UI) / COUNT_ACC
- * where
- * UI = 1 / (2 * F) in seconds
- * COUNT_ACC = counter accuracy in seconds
- * For ANN and CHV, COUNT_ACC = 0.0625 ns
- * For BXT, COUNT_ACC = 0.125 ns
- * A and B are coefficients from the table below,
- * depending whether the register minimum or maximum value is
- * calculated.
- * Minimum Maximum
- * Clock lane A B A B
- * reg_rx_csi_dly_cnt_termen_clane 0 0 38 0
- * reg_rx_csi_dly_cnt_settle_clane 95 -8 300 -16
- * Data lanes
- * reg_rx_csi_dly_cnt_termen_dlane0 0 0 35 4
- * reg_rx_csi_dly_cnt_settle_dlane0 85 -2 145 -6
- * reg_rx_csi_dly_cnt_termen_dlane1 0 0 35 4
- * reg_rx_csi_dly_cnt_settle_dlane1 85 -2 145 -6
- * reg_rx_csi_dly_cnt_termen_dlane2 0 0 35 4
- * reg_rx_csi_dly_cnt_settle_dlane2 85 -2 145 -6
- * reg_rx_csi_dly_cnt_termen_dlane3 0 0 35 4
- * reg_rx_csi_dly_cnt_settle_dlane3 85 -2 145 -6
- *
- * We use the minimum values in the calculations below.
- */
- static const short int coeff_clk_termen[] = { 0, 0 };
- static const short int coeff_clk_settle[] = { 95, -8 };
- static const short int coeff_dat_termen[] = { 0, 0 };
- static const short int coeff_dat_settle[] = { 85, -2 };
- static const int TERMEN_DEFAULT = 0 * 0;
- static const int SETTLE_DEFAULT = 0x480;
- static const hrt_address csi2_port_base[] = {
- [ATOMISP_CAMERA_PORT_PRIMARY] = CSI2_PORT_A_BASE,
- [ATOMISP_CAMERA_PORT_SECONDARY] = CSI2_PORT_B_BASE,
- [ATOMISP_CAMERA_PORT_TERTIARY] = CSI2_PORT_C_BASE,
- };
- /* Number of lanes on each port, excluding clock lane */
- static const unsigned char csi2_port_lanes[] = {
- [ATOMISP_CAMERA_PORT_PRIMARY] = 4,
- [ATOMISP_CAMERA_PORT_SECONDARY] = 2,
- [ATOMISP_CAMERA_PORT_TERTIARY] = 2,
- };
- static const hrt_address csi2_lane_base[] = {
- CSI2_LANE_CL_BASE,
- CSI2_LANE_D0_BASE,
- CSI2_LANE_D1_BASE,
- CSI2_LANE_D2_BASE,
- CSI2_LANE_D3_BASE,
- };
-
- int clk_termen;
- int clk_settle;
- int dat_termen;
- int dat_settle;
-
- struct v4l2_control ctrl;
- struct atomisp_device *isp = asd->isp;
- struct camera_mipi_info *mipi_info;
- int mipi_freq = 0;
- enum atomisp_camera_port port;
-
- int n;
-
- mipi_info = atomisp_to_sensor_mipi_info(
- isp->inputs[asd->input_curr].camera);
- port = mipi_info->port;
-
- ctrl.id = V4L2_CID_LINK_FREQ;
- if (v4l2_g_ctrl
- (isp->inputs[asd->input_curr].camera->ctrl_handler, &ctrl) == 0)
- mipi_freq = ctrl.value;
-
- clk_termen = atomisp_csi2_configure_calc(coeff_clk_termen,
- mipi_freq, TERMEN_DEFAULT);
- clk_settle = atomisp_csi2_configure_calc(coeff_clk_settle,
- mipi_freq, SETTLE_DEFAULT);
- dat_termen = atomisp_csi2_configure_calc(coeff_dat_termen,
- mipi_freq, TERMEN_DEFAULT);
- dat_settle = atomisp_csi2_configure_calc(coeff_dat_settle,
- mipi_freq, SETTLE_DEFAULT);
- for (n = 0; n < csi2_port_lanes[port] + 1; n++) {
- hrt_address base = csi2_port_base[port] + csi2_lane_base[n];
- atomisp_store_uint32(base + CSI2_REG_RX_CSI_DLY_CNT_TERMEN,
- n == 0 ? clk_termen : dat_termen);
- atomisp_store_uint32(base + CSI2_REG_RX_CSI_DLY_CNT_SETTLE,
- n == 0 ? clk_settle : dat_settle);
- }
-}
-
-void atomisp_csi2_configure(struct atomisp_sub_device *asd)
-{
- if (IS_HWREVISION(asd->isp, ATOMISP_HW_REVISION_ISP2401))
- atomisp_csi2_configure_isp2401(asd);
-}
-
-/*
- * atomisp_mipi_csi2_cleanup - Routine for module driver cleanup
-*/
-void atomisp_mipi_csi2_cleanup(struct atomisp_device *isp)
-{
-}
-
-#ifndef ISP2401
-
-#endif
-int atomisp_mipi_csi2_init(struct atomisp_device *isp)
-{
- struct atomisp_mipi_csi2_device *csi2_port;
- unsigned int i;
- int ret;
-
- for (i = 0; i < ATOMISP_CAMERA_NR_PORTS; i++) {
- csi2_port = &isp->csi2_port[i];
- csi2_port->isp = isp;
- ret = mipi_csi2_init_entities(csi2_port, i);
- if (ret < 0)
- goto fail;
- }
-
- return 0;
-
-fail:
- atomisp_mipi_csi2_cleanup(isp);
- return ret;
-}
-