mirror of
https://github.com/torvalds/linux.git
synced 2025-12-07 20:06:24 +00:00
media: imx: imx7_mipi_csis: Add i.MX8MM support
The CSI-2 receiver in the i.MX8MM is a newer version of the one found in the i.MX7. Differences are minimal, support it in the imx7_mipi_csis driver. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Rui Miguel Silva <rmfrfs@gmail.com> Tested-by: Frieder Schrempf <frieder.schrempf@kontron.de> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
85b62ff2cb
commit
f0e7cfbb43
@@ -18,6 +18,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
@@ -283,21 +284,33 @@ enum mipi_csis_clk {
|
|||||||
MIPI_CSIS_CLK_PCLK,
|
MIPI_CSIS_CLK_PCLK,
|
||||||
MIPI_CSIS_CLK_WRAP,
|
MIPI_CSIS_CLK_WRAP,
|
||||||
MIPI_CSIS_CLK_PHY,
|
MIPI_CSIS_CLK_PHY,
|
||||||
|
MIPI_CSIS_CLK_AXI,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const mipi_csis_clk_id[] = {
|
static const char * const mipi_csis_clk_id[] = {
|
||||||
"pclk",
|
"pclk",
|
||||||
"wrap",
|
"wrap",
|
||||||
"phy",
|
"phy",
|
||||||
|
"axi",
|
||||||
|
};
|
||||||
|
|
||||||
|
enum mipi_csis_version {
|
||||||
|
MIPI_CSIS_V3_3,
|
||||||
|
MIPI_CSIS_V3_6_3,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mipi_csis_info {
|
||||||
|
enum mipi_csis_version version;
|
||||||
|
unsigned int num_clocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct csi_state {
|
struct csi_state {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
unsigned int num_clks;
|
|
||||||
struct clk_bulk_data *clks;
|
struct clk_bulk_data *clks;
|
||||||
struct reset_control *mrst;
|
struct reset_control *mrst;
|
||||||
struct regulator *mipi_phy_regulator;
|
struct regulator *mipi_phy_regulator;
|
||||||
|
const struct mipi_csis_info *info;
|
||||||
u8 index;
|
u8 index;
|
||||||
|
|
||||||
struct v4l2_subdev sd;
|
struct v4l2_subdev sd;
|
||||||
@@ -539,6 +552,7 @@ static void mipi_csis_set_params(struct csi_state *state)
|
|||||||
val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
|
val = mipi_csis_read(state, MIPI_CSIS_CMN_CTRL);
|
||||||
val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK;
|
val &= ~MIPI_CSIS_CMN_CTRL_LANE_NR_MASK;
|
||||||
val |= (lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET;
|
val |= (lanes - 1) << MIPI_CSIS_CMN_CTRL_LANE_NR_OFFSET;
|
||||||
|
if (state->info->version == MIPI_CSIS_V3_3)
|
||||||
val |= MIPI_CSIS_CMN_CTRL_INTER_MODE;
|
val |= MIPI_CSIS_CMN_CTRL_INTER_MODE;
|
||||||
mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
|
mipi_csis_write(state, MIPI_CSIS_CMN_CTRL, val);
|
||||||
|
|
||||||
@@ -578,12 +592,12 @@ static void mipi_csis_set_params(struct csi_state *state)
|
|||||||
|
|
||||||
static int mipi_csis_clk_enable(struct csi_state *state)
|
static int mipi_csis_clk_enable(struct csi_state *state)
|
||||||
{
|
{
|
||||||
return clk_bulk_prepare_enable(state->num_clks, state->clks);
|
return clk_bulk_prepare_enable(state->info->num_clocks, state->clks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mipi_csis_clk_disable(struct csi_state *state)
|
static void mipi_csis_clk_disable(struct csi_state *state)
|
||||||
{
|
{
|
||||||
clk_bulk_disable_unprepare(state->num_clks, state->clks);
|
clk_bulk_disable_unprepare(state->info->num_clocks, state->clks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mipi_csis_clk_get(struct csi_state *state)
|
static int mipi_csis_clk_get(struct csi_state *state)
|
||||||
@@ -591,17 +605,17 @@ static int mipi_csis_clk_get(struct csi_state *state)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
state->num_clks = ARRAY_SIZE(mipi_csis_clk_id);
|
state->clks = devm_kcalloc(state->dev, state->info->num_clocks,
|
||||||
state->clks = devm_kcalloc(state->dev, state->num_clks,
|
|
||||||
sizeof(*state->clks), GFP_KERNEL);
|
sizeof(*state->clks), GFP_KERNEL);
|
||||||
|
|
||||||
if (!state->clks)
|
if (!state->clks)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < state->num_clks; i++)
|
for (i = 0; i < state->info->num_clocks; i++)
|
||||||
state->clks[i].id = mipi_csis_clk_id[i];
|
state->clks[i].id = mipi_csis_clk_id[i];
|
||||||
|
|
||||||
ret = devm_clk_bulk_get(state->dev, state->num_clks, state->clks);
|
ret = devm_clk_bulk_get(state->dev, state->info->num_clocks,
|
||||||
|
state->clks);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -666,16 +680,25 @@ static irqreturn_t mipi_csis_irq_handler(int irq, void *dev_id)
|
|||||||
|
|
||||||
static int mipi_csis_phy_enable(struct csi_state *state)
|
static int mipi_csis_phy_enable(struct csi_state *state)
|
||||||
{
|
{
|
||||||
|
if (state->info->version != MIPI_CSIS_V3_3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return regulator_enable(state->mipi_phy_regulator);
|
return regulator_enable(state->mipi_phy_regulator);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mipi_csis_phy_disable(struct csi_state *state)
|
static int mipi_csis_phy_disable(struct csi_state *state)
|
||||||
{
|
{
|
||||||
|
if (state->info->version != MIPI_CSIS_V3_3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return regulator_disable(state->mipi_phy_regulator);
|
return regulator_disable(state->mipi_phy_regulator);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mipi_csis_phy_reset(struct csi_state *state)
|
static void mipi_csis_phy_reset(struct csi_state *state)
|
||||||
{
|
{
|
||||||
|
if (state->info->version != MIPI_CSIS_V3_3)
|
||||||
|
return;
|
||||||
|
|
||||||
reset_control_assert(state->mrst);
|
reset_control_assert(state->mrst);
|
||||||
msleep(20);
|
msleep(20);
|
||||||
reset_control_deassert(state->mrst);
|
reset_control_deassert(state->mrst);
|
||||||
@@ -683,6 +706,9 @@ static void mipi_csis_phy_reset(struct csi_state *state)
|
|||||||
|
|
||||||
static int mipi_csis_phy_init(struct csi_state *state)
|
static int mipi_csis_phy_init(struct csi_state *state)
|
||||||
{
|
{
|
||||||
|
if (state->info->version != MIPI_CSIS_V3_3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Get MIPI PHY reset and regulator. */
|
/* Get MIPI PHY reset and regulator. */
|
||||||
state->mrst = devm_reset_control_get_exclusive(state->dev, NULL);
|
state->mrst = devm_reset_control_get_exclusive(state->dev, NULL);
|
||||||
if (IS_ERR(state->mrst))
|
if (IS_ERR(state->mrst))
|
||||||
@@ -1322,6 +1348,7 @@ static int mipi_csis_probe(struct platform_device *pdev)
|
|||||||
spin_lock_init(&state->slock);
|
spin_lock_init(&state->slock);
|
||||||
|
|
||||||
state->dev = dev;
|
state->dev = dev;
|
||||||
|
state->info = of_device_get_match_data(dev);
|
||||||
|
|
||||||
memcpy(state->events, mipi_csis_events, sizeof(state->events));
|
memcpy(state->events, mipi_csis_events, sizeof(state->events));
|
||||||
|
|
||||||
@@ -1430,7 +1457,19 @@ static int mipi_csis_remove(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id mipi_csis_of_match[] = {
|
static const struct of_device_id mipi_csis_of_match[] = {
|
||||||
{ .compatible = "fsl,imx7-mipi-csi2", },
|
{
|
||||||
|
.compatible = "fsl,imx7-mipi-csi2",
|
||||||
|
.data = &(const struct mipi_csis_info){
|
||||||
|
.version = MIPI_CSIS_V3_3,
|
||||||
|
.num_clocks = 3,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
.compatible = "fsl,imx8mm-mipi-csi2",
|
||||||
|
.data = &(const struct mipi_csis_info){
|
||||||
|
.version = MIPI_CSIS_V3_6_3,
|
||||||
|
.num_clocks = 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
{ /* sentinel */ },
|
{ /* sentinel */ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
|
MODULE_DEVICE_TABLE(of, mipi_csis_of_match);
|
||||||
@@ -1447,6 +1486,6 @@ static struct platform_driver mipi_csis_driver = {
|
|||||||
|
|
||||||
module_platform_driver(mipi_csis_driver);
|
module_platform_driver(mipi_csis_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("i.MX7 MIPI CSI-2 Receiver driver");
|
MODULE_DESCRIPTION("i.MX7 & i.MX8 MIPI CSI-2 receiver driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_ALIAS("platform:imx7-mipi-csi2");
|
MODULE_ALIAS("platform:imx7-mipi-csi2");
|
||||||
|
|||||||
Reference in New Issue
Block a user