Commit e80cb1fa authored by Sylwester Nawrocki's avatar Sylwester Nawrocki Committed by Mauro Carvalho Chehab

[media] s5p-fimc: Add device tree support for FIMC device driver

This patch adds device tree support for FIMC driver on S5PV210
and Exynos4 SoCs.
The FIMC IP block's features and quirks encoded statically in
the driver are now parsed from the device tree. Once all relevant
platforms are converted to device tree based booting the FIMC
variant data structures will all be removed from the driver.
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 02399e35
Samsung S5P/EXYNOS SoC Camera Subsystem (FIMC)
----------------------------------------------
The S5P/Exynos SoC Camera subsystem comprises of multiple sub-devices
represented by separate device tree nodes. Currently this includes: FIMC (in
the S5P SoCs series known as CAMIF), MIPI CSIS, FIMC-LITE and FIMC-IS (ISP).
The sub-subdevices are defined as child nodes of the common 'camera' node which
also includes common properties of the whole subsystem not really specific to
any single sub-device, like common camera port pins or the CAMCLK clock outputs
for external image sensors attached to an SoC.
Common 'camera' node
--------------------
Required properties:
- compatible : must be "samsung,fimc", "simple-bus"
- clocks : list of clock specifiers, corresponding to entries in
clock-names property;
- clock-names : must contain "fimc", "sclk_fimc" entries, matching entries
in the clocks property.
The 'camera' node must include at least one 'fimc' child node.
'fimc' device nodes
-------------------
Required properties:
- compatible: "samsung,s5pv210-fimc" for S5PV210, "samsung,exynos4210-fimc"
for Exynos4210 and "samsung,exynos4212-fimc" for Exynos4x12 SoCs;
- reg: physical base address and length of the registers set for the device;
- interrupts: should contain FIMC interrupt;
- clocks: list of clock specifiers, must contain an entry for each required
entry in clock-names;
- clock-names: must include "fimc", "sclk_fimc", "mux" entries and optionally
"parent" entry.
- samsung,pix-limits: an array of maximum supported image sizes in pixels, for
details refer to Table 2-1 in the S5PV210 SoC User Manual; The meaning of
each cell is as follows:
0 - scaler input horizontal size,
1 - input horizontal size for the scaler bypassed,
2 - REAL_WIDTH without input rotation,
3 - REAL_HEIGHT with input rotation,
- samsung,sysreg: a phandle to the SYSREG node.
Each FIMC device should have an alias in the aliases node, in the form of
fimc<n>, where <n> is an integer specifying the IP block instance.
Optional properties:
- clock-frequency: maximum FIMC local clock (LCLK) frequency;
- samsung,min-pix-sizes: an array specyfing minimum image size in pixels at
the FIMC input and output DMA, in the first and second cell respectively.
Default value when this property is not present is <16 16>;
- samsung,min-pix-alignment: minimum supported image height alignment (first
cell) and the horizontal image offset (second cell). The values are in pixels
and default to <2 1> when this property is not present;
- samsung,mainscaler-ext: a boolean property indicating whether the FIMC IP
supports extended image size and has CIEXTEN register;
- samsung,rotators: a bitmask specifying whether this IP has the input and
the output rotator. Bits 4 and 0 correspond to input and output rotator
respectively. If a rotator is present its corresponding bit should be set.
Default value when this property is not specified is 0x11.
- samsung,cam-if: a bolean property indicating whether the IP block includes
the camera input interface.
- samsung,isp-wb: this property must be present if the IP block has the ISP
writeback input.
- samsung,lcd-wb: this property must be present if the IP block has the LCD
writeback input.
Example:
aliases {
fimc0 = &fimc_0;
};
camera {
compatible = "samsung,fimc", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
status = "okay";
fimc_0: fimc@11800000 {
compatible = "samsung,exynos4210-fimc";
reg = <0x11800000 0x1000>;
interrupts = <0 85 0>;
status = "okay";
};
csis_0: csis@11880000 {
compatible = "samsung,exynos4210-csis";
reg = <0x11880000 0x1000>;
interrupts = <0 78 0>;
};
};
The MIPI-CSIS device binding is defined in samsung-mipi-csis.txt.
...@@ -65,7 +65,7 @@ static int fimc_capture_hw_init(struct fimc_dev *fimc) ...@@ -65,7 +65,7 @@ static int fimc_capture_hw_init(struct fimc_dev *fimc)
fimc_hw_set_effect(ctx); fimc_hw_set_effect(ctx);
fimc_hw_set_output_path(ctx); fimc_hw_set_output_path(ctx);
fimc_hw_set_out_dma(ctx); fimc_hw_set_out_dma(ctx);
if (fimc->variant->has_alpha) if (fimc->drv_data->alpha_color)
fimc_hw_set_rgb_alpha(ctx); fimc_hw_set_rgb_alpha(ctx);
clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
} }
...@@ -168,7 +168,7 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx) ...@@ -168,7 +168,7 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx)
fimc_hw_set_effect(ctx); fimc_hw_set_effect(ctx);
fimc_prepare_dma_offset(ctx, &ctx->d_frame); fimc_prepare_dma_offset(ctx, &ctx->d_frame);
fimc_hw_set_out_dma(ctx); fimc_hw_set_out_dma(ctx);
if (fimc->variant->has_alpha) if (fimc->drv_data->alpha_color)
fimc_hw_set_rgb_alpha(ctx); fimc_hw_set_rgb_alpha(ctx);
clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); clear_bit(ST_CAPT_APPLY_CFG, &fimc->state);
...@@ -1802,7 +1802,7 @@ int fimc_initialize_capture_subdev(struct fimc_dev *fimc) ...@@ -1802,7 +1802,7 @@ int fimc_initialize_capture_subdev(struct fimc_dev *fimc)
v4l2_subdev_init(sd, &fimc_subdev_ops); v4l2_subdev_init(sd, &fimc_subdev_ops);
sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE; sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->pdev->id); snprintf(sd->name, sizeof(sd->name), "FIMC.%d", fimc->id);
fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK; fimc->vid_cap.sd_pads[FIMC_SD_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; fimc->vid_cap.sd_pads[FIMC_SD_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
......
This diff is collapsed.
...@@ -42,6 +42,10 @@ ...@@ -42,6 +42,10 @@
#define FIMC_CAMIF_MAX_HEIGHT 0x2000 #define FIMC_CAMIF_MAX_HEIGHT 0x2000
#define FIMC_MAX_JPEG_BUF_SIZE (10 * SZ_1M) #define FIMC_MAX_JPEG_BUF_SIZE (10 * SZ_1M)
#define FIMC_MAX_PLANES 3 #define FIMC_MAX_PLANES 3
#define FIMC_PIX_LIMITS_MAX 4
#define FIMC_DEF_MIN_SIZE 16
#define FIMC_DEF_HEIGHT_ALIGN 2
#define FIMC_DEF_HOR_OFFS_ALIGN 1
/* indices to the clocks array */ /* indices to the clocks array */
enum { enum {
...@@ -365,10 +369,8 @@ struct fimc_pix_limit { ...@@ -365,10 +369,8 @@ struct fimc_pix_limit {
/** /**
* struct fimc_variant - FIMC device variant information * struct fimc_variant - FIMC device variant information
* @pix_hoff: indicate whether horizontal offset is in pixels or in bytes
* @has_inp_rot: set if has input rotator * @has_inp_rot: set if has input rotator
* @has_out_rot: set if has output rotator * @has_out_rot: set if has output rotator
* @has_cistatus2: 1 if CISTATUS2 register is present in this IP revision
* @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register * @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register
* are present in this IP revision * are present in this IP revision
* @has_cam_if: set if this instance has a camera input interface * @has_cam_if: set if this instance has a camera input interface
...@@ -378,23 +380,18 @@ struct fimc_pix_limit { ...@@ -378,23 +380,18 @@ struct fimc_pix_limit {
* @min_out_pixsize: minimum output pixel size * @min_out_pixsize: minimum output pixel size
* @hor_offs_align: horizontal pixel offset aligment * @hor_offs_align: horizontal pixel offset aligment
* @min_vsize_align: minimum vertical pixel size alignment * @min_vsize_align: minimum vertical pixel size alignment
* @out_buf_count: the number of buffers in output DMA sequence
*/ */
struct fimc_variant { struct fimc_variant {
unsigned int pix_hoff:1;
unsigned int has_inp_rot:1; unsigned int has_inp_rot:1;
unsigned int has_out_rot:1; unsigned int has_out_rot:1;
unsigned int has_cistatus2:1;
unsigned int has_mainscaler_ext:1; unsigned int has_mainscaler_ext:1;
unsigned int has_cam_if:1; unsigned int has_cam_if:1;
unsigned int has_isp_wb:1; unsigned int has_isp_wb:1;
unsigned int has_alpha:1;
const struct fimc_pix_limit *pix_limit; const struct fimc_pix_limit *pix_limit;
u16 min_inp_pixsize; u16 min_inp_pixsize;
u16 min_out_pixsize; u16 min_out_pixsize;
u16 hor_offs_align; u16 hor_offs_align;
u16 min_vsize_align; u16 min_vsize_align;
u16 out_buf_count;
}; };
/** /**
...@@ -402,11 +399,20 @@ struct fimc_variant { ...@@ -402,11 +399,20 @@ struct fimc_variant {
* @variant: variant information for this device * @variant: variant information for this device
* @num_entities: number of fimc instances available in a SoC * @num_entities: number of fimc instances available in a SoC
* @lclk_frequency: local bus clock frequency * @lclk_frequency: local bus clock frequency
* @cistatus2: 1 if the FIMC IPs have CISTATUS2 register
* @dma_pix_hoff: the horizontal DMA offset unit: 1 - pixels, 0 - bytes
* @alpha_color: 1 if alpha color component is supported
* @out_buf_count: maximum number of output DMA buffers supported
*/ */
struct fimc_drvdata { struct fimc_drvdata {
const struct fimc_variant *variant[FIMC_MAX_DEVS]; const struct fimc_variant *variant[FIMC_MAX_DEVS];
int num_entities; int num_entities;
unsigned long lclk_frequency; unsigned long lclk_frequency;
/* Fields common to all FIMC IP instances */
u8 cistatus2;
u8 dma_pix_hoff;
u8 alpha_color;
u8 out_buf_count;
}; };
#define fimc_get_drvdata(_pdev) \ #define fimc_get_drvdata(_pdev) \
...@@ -438,6 +444,7 @@ struct fimc_dev { ...@@ -438,6 +444,7 @@ struct fimc_dev {
struct platform_device *pdev; struct platform_device *pdev;
struct s5p_platform_fimc *pdata; struct s5p_platform_fimc *pdata;
const struct fimc_variant *variant; const struct fimc_variant *variant;
const struct fimc_drvdata *drv_data;
u16 id; u16 id;
struct clk *clock[MAX_FIMC_CLOCKS]; struct clk *clock[MAX_FIMC_CLOCKS];
void __iomem *regs; void __iomem *regs;
......
...@@ -152,7 +152,7 @@ static void fimc_device_run(void *priv) ...@@ -152,7 +152,7 @@ static void fimc_device_run(void *priv)
fimc_hw_set_rotation(ctx); fimc_hw_set_rotation(ctx);
fimc_hw_set_effect(ctx); fimc_hw_set_effect(ctx);
fimc_hw_set_out_dma(ctx); fimc_hw_set_out_dma(ctx);
if (fimc->variant->has_alpha) if (fimc->drv_data->alpha_color)
fimc_hw_set_rgb_alpha(ctx); fimc_hw_set_rgb_alpha(ctx);
fimc_hw_set_output_path(ctx); fimc_hw_set_output_path(ctx);
} }
......
...@@ -35,7 +35,7 @@ void fimc_hw_reset(struct fimc_dev *dev) ...@@ -35,7 +35,7 @@ void fimc_hw_reset(struct fimc_dev *dev)
cfg &= ~FIMC_REG_CIGCTRL_SWRST; cfg &= ~FIMC_REG_CIGCTRL_SWRST;
writel(cfg, dev->regs + FIMC_REG_CIGCTRL); writel(cfg, dev->regs + FIMC_REG_CIGCTRL);
if (dev->variant->out_buf_count > 4) if (dev->drv_data->out_buf_count > 4)
fimc_hw_set_dma_seq(dev, 0xF); fimc_hw_set_dma_seq(dev, 0xF);
} }
...@@ -747,7 +747,7 @@ s32 fimc_hw_get_frame_index(struct fimc_dev *dev) ...@@ -747,7 +747,7 @@ s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
{ {
s32 reg; s32 reg;
if (dev->variant->has_cistatus2) { if (dev->drv_data->cistatus2) {
reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f; reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
return reg - 1; return reg - 1;
} }
...@@ -763,7 +763,7 @@ s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev) ...@@ -763,7 +763,7 @@ s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
{ {
s32 reg; s32 reg;
if (!dev->variant->has_cistatus2) if (!dev->drv_data->cistatus2)
return -1; return -1;
reg = readl(dev->regs + FIMC_REG_CISTATUS2); reg = readl(dev->regs + FIMC_REG_CISTATUS2);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment