[media] exynos4-is: Add support for Exynos5250 MIPI-CSIS

Add compatible property for the Exynos5250 and enable the frame start
and frame end interrupts. These interrupts are needed for the Exynos5
FIMC-IS firmware. The driver enables those interrupt only where available,
depending on the 'compatible' property. This can be optimized further,
by exposing some API at the subdev driver, so the host driver can enable
extra interrupts only for the image processing chains involving FIMC-IS.

Signed-off-by: Shaik Ameer Basha <shaik.ameer@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Sylwester Nawrocki 2013-05-31 10:38:23 -03:00 committed by Mauro Carvalho Chehab
parent 086eca2905
commit f7354e6c23
2 changed files with 58 additions and 13 deletions

View File

@ -5,8 +5,8 @@ Required properties:
- compatible : "samsung,s5pv210-csis" for S5PV210 (S5PC110),
"samsung,exynos4210-csis" for Exynos4210 (S5PC210),
"samsung,exynos4212-csis" for Exynos4212/Exynos4412
SoC series;
"samsung,exynos4212-csis" for Exynos4212/Exynos4412,
"samsung,exynos5250-csis" for Exynos5250;
- reg : offset and length of the register set for the device;
- interrupts : should contain MIPI CSIS interrupt; the format of the
interrupt specifier depends on the interrupt controller;

View File

@ -1,8 +1,8 @@
/*
* Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
* Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver
*
* Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
* Sylwester Nawrocki <s.nawrocki@samsung.com>
* Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
* Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
*
* 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
@ -66,11 +66,12 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
/* Interrupt mask */
#define S5PCSIS_INTMSK 0x10
#define S5PCSIS_INTMSK_EN_ALL 0xf000103f
#define S5PCSIS_INTMSK_EVEN_BEFORE (1 << 31)
#define S5PCSIS_INTMSK_EVEN_AFTER (1 << 30)
#define S5PCSIS_INTMSK_ODD_BEFORE (1 << 29)
#define S5PCSIS_INTMSK_ODD_AFTER (1 << 28)
#define S5PCSIS_INTMSK_FRAME_START (1 << 27)
#define S5PCSIS_INTMSK_FRAME_END (1 << 26)
#define S5PCSIS_INTMSK_ERR_SOT_HS (1 << 12)
#define S5PCSIS_INTMSK_ERR_LOST_FS (1 << 5)
#define S5PCSIS_INTMSK_ERR_LOST_FE (1 << 4)
@ -78,6 +79,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
#define S5PCSIS_INTMSK_ERR_ECC (1 << 2)
#define S5PCSIS_INTMSK_ERR_CRC (1 << 1)
#define S5PCSIS_INTMSK_ERR_UNKNOWN (1 << 0)
#define S5PCSIS_INTMSK_EXYNOS4_EN_ALL 0xf000103f
#define S5PCSIS_INTMSK_EXYNOS5_EN_ALL 0xfc00103f
/* Interrupt source */
#define S5PCSIS_INTSRC 0x14
@ -88,6 +91,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-2)");
#define S5PCSIS_INTSRC_ODD_AFTER (1 << 28)
#define S5PCSIS_INTSRC_ODD (0x3 << 28)
#define S5PCSIS_INTSRC_NON_IMAGE_DATA (0xff << 28)
#define S5PCSIS_INTSRC_FRAME_START (1 << 27)
#define S5PCSIS_INTSRC_FRAME_END (1 << 26)
#define S5PCSIS_INTSRC_ERR_SOT_HS (0xf << 12)
#define S5PCSIS_INTSRC_ERR_LOST_FS (1 << 5)
#define S5PCSIS_INTSRC_ERR_LOST_FE (1 << 4)
@ -151,6 +156,9 @@ static const struct s5pcsis_event s5pcsis_events[] = {
{ S5PCSIS_INTSRC_EVEN_AFTER, "Non-image data after even frame" },
{ S5PCSIS_INTSRC_ODD_BEFORE, "Non-image data before odd frame" },
{ S5PCSIS_INTSRC_ODD_AFTER, "Non-image data after odd frame" },
/* Frame start/end */
{ S5PCSIS_INTSRC_FRAME_START, "Frame Start" },
{ S5PCSIS_INTSRC_FRAME_END, "Frame End" },
};
#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
@ -159,6 +167,11 @@ struct csis_pktbuf {
unsigned int len;
};
struct csis_drvdata {
/* Mask of all used interrupts in S5PCSIS_INTMSK register */
u32 interrupt_mask;
};
/**
* struct csis_state - the driver's internal state data structure
* @lock: mutex serializing the subdev and power management operations,
@ -171,6 +184,7 @@ struct csis_pktbuf {
* @supplies: CSIS regulator supplies
* @clock: CSIS clocks
* @irq: requested s5p-mipi-csis irq number
* @interrupt_mask: interrupt mask of the all used interrupts
* @flags: the state variable for power and streaming control
* @clock_frequency: device bus clock frequency
* @hs_settle: HS-RX settle time
@ -193,6 +207,7 @@ struct csis_state {
struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
struct clk *clock[NUM_CSIS_CLOCKS];
int irq;
u32 interrupt_mask;
u32 flags;
u32 clk_frequency;
@ -274,9 +289,10 @@ static const struct csis_pix_format *find_csis_format(
static void s5pcsis_enable_interrupts(struct csis_state *state, bool on)
{
u32 val = s5pcsis_read(state, S5PCSIS_INTMSK);
val = on ? val | S5PCSIS_INTMSK_EN_ALL :
val & ~S5PCSIS_INTMSK_EN_ALL;
if (on)
val |= state->interrupt_mask;
else
val &= ~state->interrupt_mask;
s5pcsis_write(state, S5PCSIS_INTMSK, val);
}
@ -771,8 +787,12 @@ static int s5pcsis_parse_dt(struct platform_device *pdev,
#define s5pcsis_parse_dt(pdev, state) (-ENOSYS)
#endif
static const struct of_device_id s5pcsis_of_match[];
static int s5pcsis_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
const struct csis_drvdata *drv_data;
struct device *dev = &pdev->dev;
struct resource *mem_res;
struct csis_state *state;
@ -787,10 +807,19 @@ static int s5pcsis_probe(struct platform_device *pdev)
spin_lock_init(&state->slock);
state->pdev = pdev;
if (dev->of_node)
if (dev->of_node) {
of_id = of_match_node(s5pcsis_of_match, dev->of_node);
if (WARN_ON(of_id == NULL))
return -EINVAL;
drv_data = of_id->data;
state->interrupt_mask = drv_data->interrupt_mask;
ret = s5pcsis_parse_dt(pdev, state);
else
} else {
ret = s5pcsis_get_platform_data(pdev, state);
}
if (ret < 0)
return ret;
@ -994,9 +1023,25 @@ static const struct dev_pm_ops s5pcsis_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(s5pcsis_suspend, s5pcsis_resume)
};
static const struct csis_drvdata exynos4_csis_drvdata = {
.interrupt_mask = S5PCSIS_INTMSK_EXYNOS4_EN_ALL,
};
static const struct csis_drvdata exynos5_csis_drvdata = {
.interrupt_mask = S5PCSIS_INTMSK_EXYNOS5_EN_ALL,
};
static const struct of_device_id s5pcsis_of_match[] = {
{ .compatible = "samsung,s5pv210-csis" },
{ .compatible = "samsung,exynos4210-csis" },
{
.compatible = "samsung,s5pv210-csis",
.data = &exynos4_csis_drvdata,
}, {
.compatible = "samsung,exynos4210-csis",
.data = &exynos4_csis_drvdata,
}, {
.compatible = "samsung,exynos5250-csis",
.data = &exynos5_csis_drvdata,
},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, s5pcsis_of_match);