]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
media:platform:tegra: Add mipical support in nvcsi
authorWenjia Zhou <wenjiaz@nvidia.com>
Wed, 3 Aug 2016 02:55:15 +0000 (19:55 -0700)
committermobile promotions <svcmobile_promotions@nvidia.com>
Wed, 24 Aug 2016 21:06:27 +0000 (14:06 -0700)
-- Add nvcsi register macro
-- Add nvcsi cil pad config
-- Add mipical CIL pad config

Change-Id: I55e3a777f36f0cbdb628afc24e4b308c16af3136
Signed-off-by: Wenjia Zhou <wenjiaz@nvidia.com>
Reviewed-on: http://git-master/r/1199640
GVS: Gerrit_Virtual_Submit
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
drivers/media/platform/tegra/camera/channel.c
drivers/media/platform/tegra/camera/mc_common.c
drivers/media/platform/tegra/csi/Makefile
drivers/media/platform/tegra/csi/csi.c
drivers/media/platform/tegra/csi/csi.h

index 4ce5f3bbb8ad480ac035b26481fce262c77423ed..1841f6e2b3a2a25cf5e66d7044125ea75f29b15d 100644 (file)
@@ -38,7 +38,8 @@
 #include <mach/io_dpd.h>
 
 #include "mc_common.h"
-#include "../vi/vi.h"
+#include "vi/vi.h"
+#include "mipical/mipi_cal.h"
 
 #define FRAMERATE      30
 #define BPP_MEM                2
@@ -700,13 +701,10 @@ static int tegra_channel_start_streaming(struct vb2_queue *vq, u32 count)
                ret = tegra_channel_set_stream(chan, true);
                if (ret < 0)
                        goto error_set_stream;
-               /*
-               nvhost_module_enable_clk(chan->vi->dev);
                tegra_mipi_bias_pad_enable();
                mutex_lock(&chan->vi->mipical_lock);
-               tegra_channel_mipi_cal(chan, 1);
+               csi_mipi_cal(chan, 1);
                mutex_unlock(&chan->vi->mipical_lock);
-               nvhost_module_disable_clk(chan->vi->dev);*/
                return ret;
        }
        chan->capture_state = CAPTURE_IDLE;
@@ -777,6 +775,7 @@ static void tegra_channel_stop_streaming(struct vb2_queue *vq)
        if (!chan->vi->pg_mode) {
                tegra_channel_set_stream(chan, false);
                media_entity_pipeline_stop(&chan->video.entity);
+               tegra_mipi_bias_pad_disable();
        }
 
        if (!chan->bypass)
@@ -1625,7 +1624,6 @@ static void tegra_channel_csi_init(struct tegra_mc_vi *vi, unsigned int index)
                /* maximum of 4 lanes are present per CSI block */
                chan->csibase[idx] = vi->iomem +
                                        TEGRA_VI_CSI_BASE(chan->port[idx]);
-               set_csi_portinfo(vi->csi, chan->port[idx], numlanes);
        }
        /* based on gang mode valid ports will be updated - set default to 1 */
        chan->valid_ports = chan->total_ports ? 1 : 0;
@@ -1642,7 +1640,7 @@ static int tegra_channel_init(struct tegra_mc_vi *vi, unsigned int index)
 
        chan->vi = vi;
        //chan->fops = vi->vi->data->channel_fops;
-       //tegra_channel_csi_init(vi, index);
+       tegra_channel_csi_init(vi, index);
 
        chan->width_align = TEGRA_WIDTH_ALIGNMENT;
        chan->stride_align = TEGRA_STRIDE_ALIGNMENT;
index c6918b72d1f464c62bcd218a6fc092b19edfcb6b..c7353768282ae48ac7519a20107bb7a81dec6250 100644 (file)
@@ -312,6 +312,7 @@ int tegra_vi_media_controller_init(struct tegra_mc_vi *mc_vi,
        mc_vi->dev = &pdev->dev;
        INIT_LIST_HEAD(&mc_vi->entities);
         mc_vi->bypass = true;
+       mutex_init(&mc_vi->mipical_lock);
        err = tegra_vi_v4l2_init(mc_vi);
        if (err < 0)
                goto mc_init_fail;
index efeb81f1380ddd9b135cfa72d9dea5d4ce9c269a..93f74f55d64cfd11afd19a92801efbf5d93ffd1e 100644 (file)
@@ -1,8 +1,9 @@
 GCOV_PROFILE := y
 ccflags-y += -I../nvhost/drivers/video/tegra/host
+ccflags-y += -I../nvhost-t18x/drivers/video/tegra/host
 ccflags-y += -I../nvhost/include
 ccflags-y += -Idrivers/video/tegra/camera
-ccflags-y += -Idrivers/media/platform/tegra/
+ccflags-y += -Idrivers/media/platform/tegra
 ccflags-y += -Werror
 
 obj-y += csi.o csi2_fops.o
index 2e6ea5763c91a6168086124e79fa0b848a4249dc..45273a553d65f54f7af64c590355f3b2ce79c733 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of.h>
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
+#include <linux/of_platform.h>
 
 #include <media/media-entity.h>
 #include <media/v4l2-async.h>
 #include "dev.h"
 #include "vi/vi.h"
 #include "csi/csi.h"
+#include "camera/mc_common.h"
+#include "mipical/mipi_cal.h"
+#include "linux/nvhost.h"
+#include "nvcsi/nvcsi.h"
 
 void set_csi_portinfo(struct tegra_csi_device *csi,
        unsigned int port, unsigned int numlanes)
@@ -199,12 +204,208 @@ void tegra_csi_stop_streaming(struct tegra_csi_device *csi,
 }
 EXPORT_SYMBOL(tegra_csi_stop_streaming);
 
+static struct tegra_csi_device *get_csi(void)
+{
+       struct device_node *np;
+       struct platform_device *dev;
+       struct nvhost_device_data *pdata;
+
+       np = of_find_node_by_name(NULL, "nvcsi");
+       if (!np) {
+               pr_err("%s: Can not find nvcsi node\n", __func__);
+               return NULL;
+       }
+       dev = of_find_device_by_node(np);
+       if (!dev) {
+               pr_err("%s:Can not find device\n", __func__);
+               return NULL;
+       }
+       pdata = platform_get_drvdata(dev);
+       if (!pdata) {
+               pr_err("%s:Can not find driver\n", __func__);
+               return NULL;
+       }
+       return &((struct nvcsi *)pdata->private_data)->csi;
+}
+
+int csi_mipi_cal(struct tegra_channel *chan, char is_bypass)
+{
+       unsigned int lanes, cur_lanes;
+       unsigned int cila, cilb;
+       struct tegra_csi_device *csi;
+       int j;
+
+       csi = get_csi();
+       if (!csi)
+               return -EINVAL;
+
+       lanes = 0;
+
+       if (chan->numlanes == 2 && chan->total_ports == 1) {
+               cila =  (0x01 << E_INPUT_LP_IO0_SHIFT) |
+                       (0x01 << E_INPUT_LP_IO1_SHIFT) |
+                       (0x01 << E_INPUT_LP_CLK) |
+                       (0x00 << PD_CLK) |
+                       (0x00 << PD_IO0) |
+                       (0x00 << PD_IO1);
+               cilb = cila;
+               switch (chan->port[0]) {
+               case PORT_A:
+                       lanes = CSIA;
+                       host1x_writel(csi->pdev, NVCSI_PHY_0_BASE +
+                                       NVCSI_CIL_A_BASE + PAD_CONFIG_0,
+                                       cila);
+                       break;
+               case PORT_B:
+                       lanes = CSIB;
+                       host1x_writel(csi->pdev, NVCSI_PHY_0_BASE +
+                                       NVCSI_CIL_B_BASE + PAD_CONFIG_0,
+                                       cilb);
+                       break;
+               case PORT_C:
+                       lanes = CSIC;
+                       host1x_writel(csi->pdev, NVCSI_PHY_1_BASE +
+                                       NVCSI_CIL_A_BASE + PAD_CONFIG_0,
+                                       cila);
+                       break;
+               case PORT_D:
+                       lanes = CSID;
+                       host1x_writel(csi->pdev, NVCSI_PHY_1_BASE +
+                                       NVCSI_CIL_B_BASE + PAD_CONFIG_0,
+                                       cilb);
+                       break;
+               case PORT_E:
+                       lanes = CSIE;
+                       host1x_writel(csi->pdev, NVCSI_PHY_2_BASE +
+                                       NVCSI_CIL_A_BASE + PAD_CONFIG_0,
+                                       cila);
+                       break;
+               case PORT_F:
+                       lanes = CSIF;
+                       host1x_writel(csi->pdev, NVCSI_PHY_2_BASE +
+                                       NVCSI_CIL_B_BASE + PAD_CONFIG_0,
+                                       cilb);
+                       break;
+               }
+       } else if (chan->numlanes == 4 && chan->total_ports == 1) {
+               cila =  (0x01 << E_INPUT_LP_IO0_SHIFT) |
+                       (0x01 << E_INPUT_LP_IO1_SHIFT) |
+                       (0x01 << E_INPUT_LP_CLK) |
+                       (0x00 << PD_CLK) |
+                       (0x00 << PD_IO0) |
+                       (0x00 << PD_IO1);
+               cilb =  (0x01 << E_INPUT_LP_IO0_SHIFT) |
+                       (0x01 << E_INPUT_LP_IO1_SHIFT) |
+                       (0x01 << PD_CLK) |
+                       (0x00 << PD_IO0) |
+                       (0x00 << PD_IO1);
+               switch (chan->port[0]) {
+               case PORT_A:
+               case PORT_B:
+                       lanes = CSIA|CSIB;
+                       host1x_writel(csi->pdev, NVCSI_PHY_0_BASE +
+                                       NVCSI_CIL_A_BASE + PAD_CONFIG_0,
+                                       cila);
+                       host1x_writel(csi->pdev, NVCSI_PHY_0_BASE +
+                                       NVCSI_CIL_B_BASE + PAD_CONFIG_0,
+                                       cilb);
+                       break;
+               case PORT_C:
+               case PORT_D:
+                       lanes = CSIC|CSID;
+                       host1x_writel(csi->pdev, NVCSI_PHY_1_BASE +
+                                       NVCSI_CIL_A_BASE + PAD_CONFIG_0,
+                                       cila);
+                       host1x_writel(csi->pdev, NVCSI_PHY_1_BASE +
+                                       NVCSI_CIL_B_BASE + PAD_CONFIG_0,
+                                       cilb);
+                       break;
+               case PORT_E:
+               case PORT_F:
+                       lanes = CSIE|CSIF;
+                       host1x_writel(csi->pdev, NVCSI_PHY_2_BASE +
+                                       NVCSI_CIL_A_BASE + PAD_CONFIG_0,
+                                       cila);
+                       host1x_writel(csi->pdev, NVCSI_PHY_2_BASE +
+                                       NVCSI_CIL_B_BASE + PAD_CONFIG_0,
+                                       cilb);
+                       break;
+               }
+       } else if (chan->numlanes == 8) {
+               cila =  (0x01 << E_INPUT_LP_IO0_SHIFT) |
+                       (0x01 << E_INPUT_LP_IO1_SHIFT) |
+                       (0x01 << E_INPUT_LP_CLK) |
+                       (0x00 << PD_CLK) |
+                       (0x00 << PD_IO0) |
+                       (0x00 << PD_IO1);
+               cilb =  (0x01 << E_INPUT_LP_IO0_SHIFT) |
+                       (0x01 << E_INPUT_LP_IO1_SHIFT) |
+                       (0x01 << PD_CLK) |
+                       (0x00 << PD_IO0) |
+                       (0x00 << PD_IO1);
+               cur_lanes = 0;
+               for (j = 0; j < chan->valid_ports; ++j) {
+                       switch (chan->port[j]) {
+                       case PORT_A:
+                       case PORT_B:
+                               cur_lanes = CSIA|CSIB;
+                               host1x_writel(csi->pdev, NVCSI_PHY_0_BASE +
+                                               NVCSI_CIL_A_BASE + PAD_CONFIG_0,
+                                               cila);
+                               host1x_writel(csi->pdev, NVCSI_PHY_0_BASE +
+                                               NVCSI_CIL_B_BASE + PAD_CONFIG_0,
+                                               cilb);
+                               break;
+                       case PORT_C:
+                       case PORT_D:
+                               cur_lanes = CSIC|CSID;
+                               host1x_writel(csi->pdev, NVCSI_PHY_1_BASE +
+                                               NVCSI_CIL_A_BASE + PAD_CONFIG_0,
+                                               cila);
+                               host1x_writel(csi->pdev, NVCSI_PHY_1_BASE +
+                                               NVCSI_CIL_B_BASE + PAD_CONFIG_0,
+                                               cilb);
+                               break;
+                       case PORT_E:
+                       case PORT_F:
+                               cur_lanes = CSIE|CSIF;
+                               host1x_writel(csi->pdev, NVCSI_PHY_2_BASE +
+                                               NVCSI_CIL_A_BASE + PAD_CONFIG_0,
+                                               cila);
+                               host1x_writel(csi->pdev, NVCSI_PHY_2_BASE +
+                                               NVCSI_CIL_B_BASE + PAD_CONFIG_0,
+                                               cilb);
+                               break;
+                       default:
+                               dev_err(csi->dev, "csi_port number: %d",
+                                               chan->port[0]);
+                               break;
+                       }
+                       lanes |= cur_lanes;
+               }
+       }
+
+       if (!lanes) {
+               dev_err(csi->dev, "Selected no CSI lane, cannot do calibration");
+               return -EINVAL;
+       }
+       return tegra_mipi_calibration(lanes);
+}
+EXPORT_SYMBOL(csi_mipi_cal);
+
 static int tegra_csi_s_stream(struct v4l2_subdev *subdev, int enable)
 {
-       struct tegra_csi_device *csi = to_csi(subdev);
+       struct tegra_csi_device *csi;
        struct tegra_channel *chan;
        int index;
 
+       csi = to_csi(subdev);
+       if (!csi)
+               return -EINVAL;
+       if (enable)
+               nvhost_module_busy(csi->pdev);
+       else
+               nvhost_module_idle(csi->pdev);
        return 0;
 
        if (csi->pg_mode)
@@ -547,7 +748,7 @@ int tegra_csi_media_controller_init(struct tegra_csi_device *csi,
        int ret, i;
 
        csi->dev = &pdev->dev;
-
+       csi->pdev = pdev;
        if (csi->pg_mode)
                ret = tegra_tpg_csi_parse_data(csi, pdev);
        else
index cd310fd80389c9d0c731ac2dbda78220424041bc..b197a0f031e80449cdc6eb17d8b239456e230d35 100644 (file)
 #include <media/v4l2-async.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-subdev.h>
+#include <linux/platform_device.h>
 
 #include <media/camera_common.h>
 #include "../camera/registers.h"
-#include <linux/platform_device.h>
-
+#include "../camera/mc_common.h"
+
+#define NVCSI_PHY_0_BASE                       0x18000
+#define NVCSI_CIL_PHY_CTRL_0                   0x0
+#define                CFG_PHY_MODE                    0x1
+#define                CFG_PHY_MODE_SHIFT              0
+#define NVCSI_CIL_CONFIG_0                     0x4
+#define                DATA_LANE_A                     0x7
+#define                DATA_LANE_A_SHIFT               0
+#define                DATA_LANE_B                     0x7
+#define                DATA_LANE_B_SHIFT               8
+#define        NVCSI_CIL_CLKEN_OVERRIDE_CTRL_0         0x8
+#define        NVCSI_CIL_PAD_CONFIG_0                  0xc
+#define NVCSI_CIL_LANE_SWIZZLE_CTRL_0          0x10
+
+#define        NVCSI_CIL_A_BASE                        0x18
+#define        SW_RESET_0                              0x0
+#define CLKEN_OVERRIDE_CTRL_0                  0x4
+#define PAD_CONFIG_0                           0x8
+#define                E_INPUT_LP_IO1_SHIFT            22
+#define                E_INPUT_LP_IO0_SHIFT            21
+#define                E_INPUT_LP_CLK                  20
+#define                PD_CLK                          18
+#define                PD_IO1                          17
+#define                PD_IO0                          16
+#define        CLK_DESKEW_CTRL_0                       0x14
+#define DATA_DESKEW_CTRL_0                     0x18
+#define POLARITY_SWIZZLE_CTRL_0                        0x40
+#define CONTROL_0                              0x44
+#define NVCSI_CIL_B_BASE                       0x7c
+
+#define NVCSI_PHY_1_BASE                       0x28000
+#define NVCSI_PHY_2_BASE                       0x38000
 
 enum tegra_csi_port_num {
        PORT_A = 0,
@@ -43,6 +75,8 @@ enum camera_gang_mode {
        CAMERA_GANG_B_T
 };
 
+struct tegra_channel;
+
 struct tegra_csi_port {
        void __iomem *pixel_parser;
        void __iomem *cil;
@@ -60,6 +94,7 @@ struct tegra_csi_device {
        struct v4l2_subdev subdev;
        struct vi *vi;
        struct device *dev;
+       struct platform_device *pdev;
        void __iomem *iomem[3];
        struct clk *clk;
        struct clk *tpg_clk;
@@ -128,4 +163,5 @@ int tegra_csi_init(struct tegra_csi_device *csi,
 int tegra_csi_media_controller_init(struct tegra_csi_device *csi,
                                struct platform_device *pdev);
 int tegra_csi_media_controller_remove(struct tegra_csi_device *csi);
+int csi_mipi_cal(struct tegra_channel *chan, char is_bypass);
 #endif