2025-05-10 21:58:58 +08:00

771 lines
22 KiB
C

/*
*************************************************************************
* Rockchip driver for CIF ISP 1.0
* (Based on Intel driver for sofiaxxx)
*
* Copyright (C) 2015 Intel Mobile Communications GmbH
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*************************************************************************
*/
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/clk.h>
#include <linux/reset.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/platform_data/rk_isp10_platform.h>
#define VI_IRCL 0x0014
#define MRV_MIPI_BASE 0x1C00
#define MRV_MIPI_CTRL 0x00
/*
* GRF_IO_VSEL
*/
#define GRF_IO_VSEL_OFFSET (0x0900)
#define DVP_V18SEL ((1 << 1) | (1 << 17))
#define DVP_V33SEL ((0 << 1) | (1 << 17))
/*
* GRF_IO_VSEL
*/
#define GRF_GPIO2B_E_OFFSET (0x0204)
#define CIF_CLKOUT_STRENGTH(a) \
((((a) & 0x03) << 3) | (0x03 << 19))
#define GRF_SOC_STATUS1 (0x0e2a4)
#define GRF_SOC_CON9_OFFSET (0x6224)
#define DPHY_RX0_TURNREQUEST_MASK (0xF << 16)
#define DPHY_RX0_TURNREQUEST_BIT (0)
#define GRF_SOC_CON21_OFFSET (0x6254)
#define DPHY_RX0_FORCERXMODE_MASK (0xF << 20)
#define DPHY_RX0_FORCERXMODE_BIT (4)
#define DPHY_RX0_FORCETXSTOPMODE_MASK (0xF << 24)
#define DPHY_RX0_FORCETXSTOPMODE_BIT (8)
#define DPHY_RX0_TURNDISABLE_MASK (0xF << 28)
#define DPHY_RX0_TURNDISABLE_BIT (12)
#define DPHY_RX0_ENABLE_MASK (0xF << 16)
#define DPHY_RX0_ENABLE_BIT (0)
#define GRF_SOC_CON23_OFFSET (0x625c)
#define DPHY_TX1RX1_TURNDISABLE_MASK (0xF << 28)
#define DPHY_TX1RX1_TURNDISABLE_BIT (12)
#define DPHY_TX1RX1_FORCERXMODE_MASK (0xF << 20)
#define DPHY_TX1RX1_FORCERXMODE_BIT (4)
#define DPHY_TX1RX1_FORCETXSTOPMODE_MASK (0xF << 24)
#define DPHY_TX1RX1_FORCETXSTOPMODE_BIT (8)
#define DPHY_TX1RX1_ENABLE_MASK (0xF << 16)
#define DPHY_TX1RX1_ENABLE_BIT (0)
#define GRF_SOC_CON24_OFFSET (0x6260)
#define DPHY_TX1RX1_MASTERSLAVEZ_MASK (0x1 << 23)
#define DPHY_TX1RX1_MASTERSLAVEZ_BIT (7)
#define DPHY_TX1RX1_BASEDIR_MASK (0x1 << 21)
#define DPHY_TX1RX1_BASEDIR_BIT (5)
#define DPHY_RX1_MASK (0x1 << 20)
#define DPHY_RX1_SEL_BIT (4)
#define GRF_SOC_CON25_OFFSET (0x6264)
#define DPHY_RX0_TESTCLK_MASK (0x1 << 25)
#define DPHY_RX0_TESTCLK_BIT (9)
#define DPHY_RX0_TESTCLR_MASK (0x1 << 26)
#define DPHY_RX0_TESTCLR_BIT (10)
#define DPHY_RX0_TESTDIN_MASK (0xFF << 16)
#define DPHY_RX0_TESTDIN_BIT (0)
#define DPHY_RX0_TESTEN_MASK (0x1 << 24)
#define DPHY_RX0_TESTEN_BIT (8)
#define DPHY_TX1RX1_TURNREQUEST_MASK (0xF << 16)
#define DPHY_TX1RX1_TURNREQUEST_BIT (0)
#define DSIHOST_PHY_SHUTDOWNZ (0x00a0)
#define DSIHOST_DPHY_RSTZ (0x00a0)
#define DSIHOST_PHY_TEST_CTRL0 (0x00b4)
#define DSIHOST_PHY_TEST_CTRL1 (0x00b8)
#define write_cifisp_reg(addr, val) \
__raw_writel(val, (addr) + isp_cfg->isp_base)
#define read_cifisp_reg(addr) \
__raw_readl((addr) + isp_cfg->isp_base)
#define write_grf_reg(addr, val) \
regmap_write(isp_cfg->regmap_grf, addr, val)
#define read_grf_reg(addr, val) \
regmap_read(isp_cfg->regmap_grf, addr, val)
#define write_dsihost_reg(addr, val) \
__raw_writel(val, (addr) + isp_cfg->dsihost_base)
#define read_dsihost_reg(addr) \
__raw_readl((addr) + isp_cfg->dsihost_base)
enum cif_isp10_isp_idx {
CIF_ISP10_ISP0 = 0,
CIF_ISP10_ISP1 = 1
};
struct cif_isp10_clk_rst_rk3399 {
struct clk *hclk_isp0_noc;
struct clk *hclk_isp0_wrapper;
struct clk *hclk_isp1_noc;
struct clk *hclk_isp1_wrapper;
struct clk *aclk_isp0_noc;
struct clk *aclk_isp0_wrapper;
struct clk *aclk_isp1_noc;
struct clk *aclk_isp1_wrapper;
struct clk *clk_isp0;
struct clk *clk_isp1;
struct clk *pclkin_isp1;
struct clk *pclk_dphy_ref;
struct clk *pclk_dphytxrx;
struct clk *pclk_dphyrx;
struct clk *cif_clk_out;
struct clk *cif_clk_pll;
struct clk *cif_clk_mipi_dsi;
struct clk *cif_clk_mipi_dphy_cfg;
};
struct cif_isp10_rk3399 {
struct regmap *regmap_grf;
void __iomem *dsihost_base;
void __iomem *isp_base;
struct cif_isp10_clk_rst_rk3399 clk_rst;
struct cif_isp10_device *cif_isp10;
enum cif_isp10_isp_idx isp_idx;
};
struct mipi_dphy_hsfreqrange {
unsigned int range_l;
unsigned int range_h;
unsigned char cfg_bit;
};
static struct mipi_dphy_hsfreqrange mipi_dphy_hsfreq_range[] = {
{80, 90, 0x00},
{90, 100, 0x10},
{100, 110, 0x20},
{110, 130, 0x01},
{130, 140, 0x11},
{140, 150, 0x21},
{150, 170, 0x02},
{170, 180, 0x12},
{180, 200, 0x22},
{200, 220, 0x03},
{220, 240, 0x13},
{240, 250, 0x23},
{250, 270, 0x4},
{270, 300, 0x14},
{300, 330, 0x5},
{330, 360, 0x15},
{360, 400, 0x25},
{400, 450, 0x06},
{450, 500, 0x16},
{500, 550, 0x07},
{550, 600, 0x17},
{600, 650, 0x08},
{650, 700, 0x18},
{700, 750, 0x09},
{750, 800, 0x19},
{800, 850, 0x29},
{850, 900, 0x39},
{900, 950, 0x0a},
{950, 1000, 0x1a},
{1000, 1050, 0x2a},
{1100, 1150, 0x3a},
{1150, 1200, 0x0b},
{1200, 1250, 0x1b},
{1250, 1300, 0x2b},
{1300, 1350, 0x0c},
{1350, 1400, 0x1c},
{1400, 1450, 0x2c},
{1450, 1500, 0x3c}
};
static int mipi_dphy0_wr_reg(struct cif_isp10_rk3399 *isp_cfg, unsigned char addr, unsigned char data)
{
/*
* TESTCLK=1
* TESTEN =1,TESTDIN=addr
* TESTCLK=0
*/
write_grf_reg(GRF_SOC_CON25_OFFSET,
DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT));
write_grf_reg(GRF_SOC_CON25_OFFSET,
((addr << DPHY_RX0_TESTDIN_BIT) | DPHY_RX0_TESTDIN_MASK
| (1 << DPHY_RX0_TESTEN_BIT) | DPHY_RX0_TESTEN_MASK));
write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK);
/*
* write data:
* TESTEN =0,TESTDIN=data
* TESTCLK=1
*/
if (data != 0xff) {
write_grf_reg(GRF_SOC_CON25_OFFSET,
((data << DPHY_RX0_TESTDIN_BIT) |
DPHY_RX0_TESTDIN_MASK | DPHY_RX0_TESTEN_MASK));
write_grf_reg(GRF_SOC_CON25_OFFSET,
DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT));
}
return 0;
}
static int mipi_dphy0_rd_reg(struct cif_isp10_rk3399 *isp_cfg, unsigned char addr)
{
int val = 0;
/*TESTCLK=1*/
write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK |
(1 << DPHY_RX0_TESTCLK_BIT));
/*TESTEN =1,TESTDIN=addr*/
write_grf_reg(GRF_SOC_CON25_OFFSET,
((addr << DPHY_RX0_TESTDIN_BIT) |
DPHY_RX0_TESTDIN_MASK |
(1 << DPHY_RX0_TESTEN_BIT) |
DPHY_RX0_TESTEN_MASK));
/*TESTCLK=0*/
write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK);
read_grf_reg(GRF_SOC_STATUS1, &val);
return val & 0xff;
}
static int mipi_dphy1_wr_reg(struct cif_isp10_rk3399 *isp_cfg, unsigned char addr, unsigned char data)
{
/*
* TESTEN =1,TESTDIN=addr
* TESTCLK=0
* TESTEN =0,TESTDIN=data
* TESTCLK=1
*/
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr));
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000000);
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00000000 | data));
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
return 0;
}
static int mipi_dphy1_rd_reg(struct cif_isp10_rk3399 *isp_cfg, unsigned char addr)
{
/* TESTEN =1,TESTDIN=addr */
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr));
/* TESTCLK=0 */
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000000);
return ((read_dsihost_reg(DSIHOST_PHY_TEST_CTRL1) & 0xff00) >> 8);
}
static int mipi_dphy_cfg(struct cif_isp10_rk3399 *isp_cfg, struct pltfrm_cam_mipi_config *para)
{
unsigned char hsfreqrange = 0xff, i;
struct mipi_dphy_hsfreqrange *hsfreqrange_p;
unsigned char datalane_en, input_sel;
hsfreqrange_p = mipi_dphy_hsfreq_range;
for (i = 0;
i < (sizeof(mipi_dphy_hsfreq_range) /
sizeof(struct mipi_dphy_hsfreqrange));
i++) {
if ((para->bit_rate > hsfreqrange_p->range_l) &&
(para->bit_rate <= hsfreqrange_p->range_h)) {
hsfreqrange = hsfreqrange_p->cfg_bit;
break;
}
hsfreqrange_p++;
}
if (hsfreqrange == 0xff)
hsfreqrange = 0x00;
hsfreqrange <<= 1;
input_sel = para->dphy_index;
datalane_en = 0;
for (i = 0; i < para->nb_lanes; i++)
datalane_en |= (1 << i);
if (input_sel == 0) {
/*
* According to the sequence of RK3399_TXRX_DPHY, the setting of isp0 mipi
* will affect txrx dphy in default state of grf_soc_con24.
*/
write_grf_reg(GRF_SOC_CON24_OFFSET,
DPHY_TX1RX1_MASTERSLAVEZ_MASK |
(0x0 << DPHY_TX1RX1_MASTERSLAVEZ_BIT) |
DPHY_TX1RX1_BASEDIR_MASK |
(0x1 << DPHY_TX1RX1_BASEDIR_BIT) |
DPHY_RX1_MASK | 0x0 << DPHY_RX1_SEL_BIT);
write_grf_reg(GRF_SOC_CON21_OFFSET,
DPHY_RX0_FORCERXMODE_MASK |
(0x0 << DPHY_RX0_FORCERXMODE_BIT) |
DPHY_RX0_FORCETXSTOPMODE_MASK |
(0x0 << DPHY_RX0_FORCETXSTOPMODE_BIT));
/* set lane num */
write_grf_reg(GRF_SOC_CON21_OFFSET,
DPHY_RX0_ENABLE_MASK |
(datalane_en << DPHY_RX0_ENABLE_BIT));
/* set lan turndisab as 1 */
write_grf_reg(GRF_SOC_CON21_OFFSET,
DPHY_RX0_TURNDISABLE_MASK |
(0xf << DPHY_RX0_TURNDISABLE_BIT));
write_grf_reg(GRF_SOC_CON21_OFFSET, (0x0 << 4) | (0xf << 20));
/* set lan turnrequest as 0 */
write_grf_reg(GRF_SOC_CON9_OFFSET,
DPHY_RX0_TURNREQUEST_MASK |
(0x0 << DPHY_RX0_TURNREQUEST_BIT));
/* phy start */
/*
* TESTCLK=1
* TESTCLR=1
* delay 100us
* TESTCLR=0
*/
write_grf_reg(GRF_SOC_CON25_OFFSET,
DPHY_RX0_TESTCLK_MASK |
(0x1 << DPHY_RX0_TESTCLK_BIT)); /* TESTCLK=1 */
write_grf_reg(GRF_SOC_CON25_OFFSET,
DPHY_RX0_TESTCLR_MASK |
(0x1 << DPHY_RX0_TESTCLR_BIT)); /* TESTCLR=1 */
usleep_range(100, 150);
/* TESTCLR=0 zyc */
write_grf_reg(GRF_SOC_CON25_OFFSET,
DPHY_RX0_TESTCLR_MASK);
usleep_range(100, 150);
/* set clock lane */
mipi_dphy0_wr_reg
(isp_cfg, 0x34, 0);
/* HS hsfreqrange & lane 0 settle bypass */
mipi_dphy0_wr_reg(isp_cfg, 0x44, hsfreqrange);
mipi_dphy0_wr_reg(isp_cfg, 0x54, 0);
mipi_dphy0_wr_reg(isp_cfg, 0x84, 0);
mipi_dphy0_wr_reg(isp_cfg, 0x94, 0);
mipi_dphy0_wr_reg(isp_cfg, 0x75, 0x04);
mipi_dphy0_rd_reg(isp_cfg, 0x75);
/* Normal operation */
/*
* TESTCLK=1
* TESTEN =0
*/
mipi_dphy0_wr_reg(isp_cfg, 0x0, -1);
write_grf_reg(GRF_SOC_CON25_OFFSET,
DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT));
write_grf_reg(GRF_SOC_CON25_OFFSET,
(DPHY_RX0_TESTEN_MASK));
write_cifisp_reg((MRV_MIPI_BASE + MRV_MIPI_CTRL),
read_cifisp_reg(MRV_MIPI_BASE + MRV_MIPI_CTRL)
| (0x0f << 8));
} else if (input_sel == 1) {
write_grf_reg(GRF_SOC_CON23_OFFSET,
DPHY_RX0_FORCERXMODE_MASK |
(0x0 << DPHY_RX0_FORCERXMODE_BIT) |
DPHY_RX0_FORCETXSTOPMODE_MASK |
(0x0 << DPHY_RX0_FORCETXSTOPMODE_BIT));
write_grf_reg(GRF_SOC_CON24_OFFSET,
DPHY_TX1RX1_MASTERSLAVEZ_MASK |
(0x0 << DPHY_TX1RX1_MASTERSLAVEZ_BIT) |
DPHY_TX1RX1_BASEDIR_MASK |
(0x1 << DPHY_TX1RX1_BASEDIR_BIT) |
DPHY_RX1_MASK | 0x0 << DPHY_RX1_SEL_BIT);
/* set lane num */
write_grf_reg(GRF_SOC_CON23_OFFSET,
DPHY_TX1RX1_ENABLE_MASK |
(datalane_en << DPHY_TX1RX1_ENABLE_BIT));
/* set lan turndisab as 1 */
write_grf_reg(GRF_SOC_CON23_OFFSET,
DPHY_TX1RX1_TURNDISABLE_MASK |
(0xf << DPHY_TX1RX1_TURNDISABLE_BIT));
write_grf_reg(GRF_SOC_CON23_OFFSET, (0x0 << 4) | (0xf << 20));
/* set lan turnrequest as 0 */
write_grf_reg(GRF_SOC_CON24_OFFSET,
DPHY_TX1RX1_TURNREQUEST_MASK |
(0x0 << DPHY_TX1RX1_TURNREQUEST_BIT));
/* phy1 start */
/*
* SHUTDOWNZ=0
* RSTZ=0
* TESTCLK=1
* TESTCLR=1 TESTCLK=1
* TESTCLR=0 TESTCLK=1
*/
write_dsihost_reg(DSIHOST_PHY_SHUTDOWNZ, 0x00000000);
write_dsihost_reg(DSIHOST_DPHY_RSTZ, 0x00000000);
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, 0x00000003);
usleep_range(100, 150);
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
usleep_range(100, 150);
/* set clock lane */
mipi_dphy1_wr_reg(isp_cfg, 0x34, 0x00);
mipi_dphy1_wr_reg(isp_cfg, 0x44, hsfreqrange);
mipi_dphy1_wr_reg(isp_cfg, 0x54, 0);
mipi_dphy1_wr_reg(isp_cfg, 0x84, 0);
mipi_dphy1_wr_reg(isp_cfg, 0x94, 0);
mipi_dphy1_wr_reg(isp_cfg, 0x75, 0x04);
mipi_dphy1_rd_reg(isp_cfg, 0x0);
/*
* TESTCLK=1
* TESTEN =0
* SHUTDOWNZ=1
* RSTZ=1
*/
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, 0x00000000);
/*SHUTDOWNZ=1, RSTZ=1*/
write_dsihost_reg(DSIHOST_DPHY_RSTZ, 0x00000003);
write_cifisp_reg((MRV_MIPI_BASE + MRV_MIPI_CTRL),
read_cifisp_reg(MRV_MIPI_BASE + MRV_MIPI_CTRL)
| (0x0f << 8));
} else {
goto fail;
}
return 0;
fail:
return -1;
}
static int soc_clk_enable(struct cif_isp10_rk3399 *isp_cfg)
{
struct cif_isp10_clk_rst_rk3399 *clk_rst = &isp_cfg->clk_rst;
if (isp_cfg->isp_idx == CIF_ISP10_ISP0) {
clk_prepare_enable(clk_rst->hclk_isp0_noc);
clk_prepare_enable(clk_rst->hclk_isp0_wrapper);
clk_prepare_enable(clk_rst->aclk_isp0_noc);
clk_prepare_enable(clk_rst->aclk_isp0_wrapper);
clk_prepare_enable(clk_rst->clk_isp0);
clk_prepare_enable(clk_rst->pclk_dphyrx);
clk_prepare_enable(clk_rst->cif_clk_out);
clk_prepare_enable(clk_rst->pclk_dphy_ref);
} else {
clk_prepare_enable(clk_rst->hclk_isp1_noc);
clk_prepare_enable(clk_rst->hclk_isp1_wrapper);
clk_prepare_enable(clk_rst->aclk_isp1_noc);
clk_prepare_enable(clk_rst->aclk_isp1_wrapper);
clk_prepare_enable(clk_rst->clk_isp1);
clk_prepare_enable(clk_rst->pclkin_isp1);
clk_prepare_enable(clk_rst->pclk_dphytxrx);
clk_prepare_enable(clk_rst->cif_clk_mipi_dsi);
clk_prepare_enable(clk_rst->cif_clk_mipi_dphy_cfg);
clk_prepare_enable(clk_rst->cif_clk_out);
clk_prepare_enable(clk_rst->pclk_dphy_ref);
}
return 0;
}
static int soc_clk_disable(struct cif_isp10_rk3399 *isp_cfg)
{
struct cif_isp10_clk_rst_rk3399 *clk_rst = &isp_cfg->clk_rst;
if (isp_cfg->isp_idx == CIF_ISP10_ISP0) {
clk_disable_unprepare(clk_rst->hclk_isp0_noc);
clk_disable_unprepare(clk_rst->hclk_isp0_wrapper);
clk_disable_unprepare(clk_rst->aclk_isp0_noc);
clk_disable_unprepare(clk_rst->aclk_isp0_wrapper);
clk_disable_unprepare(clk_rst->clk_isp0);
clk_disable_unprepare(clk_rst->pclk_dphyrx);
if (!IS_ERR_OR_NULL(clk_rst->cif_clk_pll))
clk_set_parent(clk_rst->cif_clk_out,
clk_rst->cif_clk_pll);
clk_disable_unprepare(clk_rst->cif_clk_out);
clk_disable_unprepare(clk_rst->pclk_dphy_ref);
} else {
clk_disable_unprepare(clk_rst->hclk_isp1_noc);
clk_disable_unprepare(clk_rst->hclk_isp1_wrapper);
clk_disable_unprepare(clk_rst->aclk_isp1_noc);
clk_disable_unprepare(clk_rst->aclk_isp1_wrapper);
clk_disable_unprepare(clk_rst->clk_isp1);
clk_disable_unprepare(clk_rst->pclkin_isp1);
clk_disable_unprepare(clk_rst->pclk_dphytxrx);
clk_disable_unprepare(clk_rst->cif_clk_mipi_dsi);
clk_disable_unprepare(clk_rst->cif_clk_mipi_dphy_cfg);
if (!IS_ERR_OR_NULL(clk_rst->cif_clk_pll))
clk_set_parent(clk_rst->cif_clk_out,
clk_rst->cif_clk_pll);
clk_disable_unprepare(clk_rst->cif_clk_out);
clk_disable_unprepare(clk_rst->pclk_dphy_ref);
}
return 0;
}
static int soc_init(struct cif_isp10_rk3399 **isp_cfg, struct pltfrm_soc_init_para *init)
{
struct cif_isp10_clk_rst_rk3399 *clk_rst;
struct platform_device *pdev = init->pdev;
struct device_node *np = pdev->dev.of_node, *node;
struct resource *res;
struct cif_isp10_rk3399 *isp_cfg_tmp;
int err;
*isp_cfg = NULL;
isp_cfg_tmp = (struct cif_isp10_rk3399 *)devm_kzalloc(
&pdev->dev,
sizeof(struct cif_isp10_rk3399),
GFP_KERNEL);
if (!isp_cfg_tmp) {
dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3399\n");
err = -ENOMEM;
goto alloc_failed;
}
node = of_parse_phandle(np, "rockchip,grf", 0);
if (node) {
isp_cfg_tmp->regmap_grf = syscon_node_to_regmap(node);
if (IS_ERR(isp_cfg_tmp->regmap_grf)) {
dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3399\n");
err = -ENODEV;
goto regmap_failed;
}
}
clk_rst = &isp_cfg_tmp->clk_rst;
if (strcmp(pdev->name, "ff910000.cif_isp") == 0) {
clk_rst->hclk_isp0_noc =
devm_clk_get(&pdev->dev, "hclk_isp0_noc");
clk_rst->hclk_isp0_wrapper =
devm_clk_get(&pdev->dev, "hclk_isp0_wrapper");
clk_rst->aclk_isp0_noc =
devm_clk_get(&pdev->dev, "aclk_isp0_noc");
clk_rst->aclk_isp0_wrapper =
devm_clk_get(&pdev->dev, "aclk_isp0_wrapper");
clk_rst->clk_isp0 =
devm_clk_get(&pdev->dev, "clk_isp0");
clk_rst->pclk_dphyrx =
devm_clk_get(&pdev->dev, "pclk_dphyrx");
clk_rst->cif_clk_out =
devm_clk_get(&pdev->dev, "clk_cif_out");
clk_rst->cif_clk_pll =
devm_clk_get(&pdev->dev, "clk_cif_pll");
clk_rst->pclk_dphy_ref =
devm_clk_get(&pdev->dev, "pclk_dphy_ref");
if (IS_ERR_OR_NULL(clk_rst->hclk_isp0_noc) ||
IS_ERR_OR_NULL(clk_rst->hclk_isp0_wrapper) ||
IS_ERR_OR_NULL(clk_rst->aclk_isp0_noc) ||
IS_ERR_OR_NULL(clk_rst->aclk_isp0_wrapper) ||
IS_ERR_OR_NULL(clk_rst->clk_isp0) ||
IS_ERR_OR_NULL(clk_rst->pclk_dphyrx) ||
IS_ERR_OR_NULL(clk_rst->cif_clk_out) ||
IS_ERR_OR_NULL(clk_rst->pclk_dphy_ref)) {
dev_err(&pdev->dev, "Get rk3399 cif isp10 clock resouce failed !\n");
err = -EINVAL;
goto clk_failed;
}
clk_set_rate(clk_rst->clk_isp0, 420000000);
isp_cfg_tmp->isp_idx = CIF_ISP10_ISP0;
} else {
res = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "dsihost-register");
if (!res) {
dev_err(&pdev->dev,
"platform_get_resource_byname dsihost-register failed\n");
err = -ENODEV;
goto regmap_failed;
}
isp_cfg_tmp->dsihost_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR_OR_NULL(isp_cfg_tmp->dsihost_base)) {
dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
if (IS_ERR(isp_cfg_tmp->dsihost_base))
err = PTR_ERR(isp_cfg_tmp->dsihost_base);
else
err = -ENODEV;
goto regmap_failed;
}
clk_rst->hclk_isp1_noc =
devm_clk_get(&pdev->dev, "hclk_isp1_noc");
clk_rst->hclk_isp1_wrapper =
devm_clk_get(&pdev->dev, "hclk_isp1_wrapper");
clk_rst->aclk_isp1_noc =
devm_clk_get(&pdev->dev, "aclk_isp1_noc");
clk_rst->aclk_isp1_wrapper =
devm_clk_get(&pdev->dev, "aclk_isp1_wrapper");
clk_rst->clk_isp1 =
devm_clk_get(&pdev->dev, "clk_isp1");
clk_rst->pclkin_isp1 =
devm_clk_get(&pdev->dev, "pclkin_isp1");
clk_rst->pclk_dphytxrx =
devm_clk_get(&pdev->dev, "pclk_dphytxrx");
clk_rst->cif_clk_mipi_dsi =
devm_clk_get(&pdev->dev, "pclk_mipi_dsi");
clk_rst->cif_clk_mipi_dphy_cfg =
devm_clk_get(&pdev->dev, "mipi_dphy_cfg");
clk_rst->cif_clk_out =
devm_clk_get(&pdev->dev, "clk_cif_out");
clk_rst->cif_clk_pll =
devm_clk_get(&pdev->dev, "clk_cif_pll");
clk_rst->pclk_dphy_ref =
devm_clk_get(&pdev->dev, "pclk_dphy_ref");
if (IS_ERR_OR_NULL(clk_rst->hclk_isp1_noc) ||
IS_ERR_OR_NULL(clk_rst->hclk_isp1_wrapper) ||
IS_ERR_OR_NULL(clk_rst->aclk_isp1_noc) ||
IS_ERR_OR_NULL(clk_rst->aclk_isp1_wrapper) ||
IS_ERR_OR_NULL(clk_rst->clk_isp1) ||
IS_ERR_OR_NULL(clk_rst->pclkin_isp1) ||
IS_ERR_OR_NULL(clk_rst->pclk_dphytxrx) ||
IS_ERR_OR_NULL(clk_rst->cif_clk_mipi_dsi) ||
IS_ERR_OR_NULL(clk_rst->cif_clk_mipi_dphy_cfg) ||
IS_ERR_OR_NULL(clk_rst->cif_clk_out) ||
IS_ERR_OR_NULL(clk_rst->pclk_dphy_ref)) {
dev_err(&pdev->dev, "Get rk3399 cif isp10 clock resouce failed !\n");
err = -EINVAL;
goto clk_failed;
}
clk_set_rate(clk_rst->clk_isp1, 420000000);
isp_cfg_tmp->isp_idx = CIF_ISP10_ISP1;
}
isp_cfg_tmp->isp_base = init->isp_base;
*isp_cfg = isp_cfg_tmp;
return 0;
clk_failed:
if (!IS_ERR_OR_NULL(clk_rst->hclk_isp0_noc))
devm_clk_put(&pdev->dev, clk_rst->hclk_isp0_noc);
if (!IS_ERR_OR_NULL(clk_rst->hclk_isp0_wrapper))
devm_clk_put(&pdev->dev, clk_rst->hclk_isp0_wrapper);
if (!IS_ERR_OR_NULL(clk_rst->aclk_isp0_noc))
devm_clk_put(&pdev->dev, clk_rst->aclk_isp0_noc);
if (!IS_ERR_OR_NULL(clk_rst->aclk_isp0_wrapper))
devm_clk_put(&pdev->dev, clk_rst->aclk_isp0_wrapper);
if (!IS_ERR_OR_NULL(clk_rst->clk_isp0))
devm_clk_put(&pdev->dev, clk_rst->clk_isp0);
if (!IS_ERR_OR_NULL(clk_rst->pclk_dphyrx))
devm_clk_put(&pdev->dev, clk_rst->pclk_dphyrx);
if (!IS_ERR_OR_NULL(clk_rst->hclk_isp1_noc))
devm_clk_put(&pdev->dev, clk_rst->hclk_isp1_noc);
if (!IS_ERR_OR_NULL(clk_rst->hclk_isp1_wrapper))
devm_clk_put(&pdev->dev, clk_rst->hclk_isp1_wrapper);
if (!IS_ERR_OR_NULL(clk_rst->aclk_isp1_noc))
devm_clk_put(&pdev->dev, clk_rst->aclk_isp1_noc);
if (!IS_ERR_OR_NULL(clk_rst->aclk_isp1_wrapper))
devm_clk_put(&pdev->dev, clk_rst->aclk_isp1_wrapper);
if (!IS_ERR_OR_NULL(clk_rst->clk_isp1))
devm_clk_put(&pdev->dev, clk_rst->clk_isp1);
if (!IS_ERR_OR_NULL(clk_rst->pclkin_isp1))
devm_clk_put(&pdev->dev, clk_rst->pclkin_isp1);
if (!IS_ERR_OR_NULL(clk_rst->pclk_dphytxrx))
devm_clk_put(&pdev->dev, clk_rst->pclk_dphytxrx);
if (!IS_ERR_OR_NULL(clk_rst->cif_clk_mipi_dsi))
devm_clk_put(&pdev->dev, clk_rst->cif_clk_mipi_dsi);
if (!IS_ERR_OR_NULL(clk_rst->cif_clk_mipi_dphy_cfg))
devm_clk_put(&pdev->dev, clk_rst->cif_clk_mipi_dphy_cfg);
if (!IS_ERR_OR_NULL(clk_rst->cif_clk_out))
devm_clk_put(&pdev->dev, clk_rst->cif_clk_out);
if (!IS_ERR_OR_NULL(clk_rst->pclk_dphy_ref))
devm_clk_put(&pdev->dev, clk_rst->pclk_dphy_ref);
regmap_failed:
alloc_failed:
return err;
}
int pltfrm_rk3399_cfg(struct pltfrm_soc_cfg_para *cfg)
{
int ret = -1;
struct cif_isp10_rk3399 *isp_cfg = NULL;
if (cfg->isp_config == NULL) {
return -1;
} else {
isp_cfg = (struct cif_isp10_rk3399 *)(*cfg->isp_config);
if (isp_cfg == NULL && cfg->cmd != PLTFRM_SOC_INIT)
return -1;
}
switch (cfg->cmd) {
case PLTFRM_MCLK_CFG: {
struct pltfrm_soc_mclk_para *mclk_para;
mclk_para = (struct pltfrm_soc_mclk_para *)cfg->cfg_para;
if (mclk_para->io_voltage == PLTFRM_IO_1V8)
write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V18SEL);
else
write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V33SEL);
write_grf_reg(GRF_GPIO2B_E_OFFSET,
CIF_CLKOUT_STRENGTH(mclk_para->drv_strength));
ret = 0;
break;
}
case PLTFRM_MIPI_DPHY_CFG:
ret = mipi_dphy_cfg(isp_cfg, (struct pltfrm_cam_mipi_config *)cfg->cfg_para);
break;
case PLTFRM_CLKEN:
ret = soc_clk_enable(isp_cfg);
break;
case PLTFRM_CLKDIS:
ret = soc_clk_disable(isp_cfg);
break;
case PLTFRM_CLKRST:
write_cifisp_reg(VI_IRCL, 0xf7f);
usleep_range(10, 15);
write_cifisp_reg(VI_IRCL, 0x00);
ret = 0;
break;
case PLTFRM_SOC_INIT:
ret = soc_init((struct cif_isp10_rk3399 **)cfg->isp_config, (struct pltfrm_soc_init_para *)cfg->cfg_para);
break;
default:
break;
}
return ret;
}