1238c84f7SMauro Carvalho Chehab /* SPDX-License-Identifier: GPL-2.0-only */
2238c84f7SMauro Carvalho Chehab /*
3238c84f7SMauro Carvalho Chehab * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
4238c84f7SMauro Carvalho Chehab */
5238c84f7SMauro Carvalho Chehab
6238c84f7SMauro Carvalho Chehab #ifndef FIMC_MDEVICE_H_
7238c84f7SMauro Carvalho Chehab #define FIMC_MDEVICE_H_
8238c84f7SMauro Carvalho Chehab
9238c84f7SMauro Carvalho Chehab #include <linux/clk.h>
10238c84f7SMauro Carvalho Chehab #include <linux/clk-provider.h>
11238c84f7SMauro Carvalho Chehab #include <linux/platform_device.h>
12238c84f7SMauro Carvalho Chehab #include <linux/mutex.h>
13238c84f7SMauro Carvalho Chehab #include <linux/of.h>
14238c84f7SMauro Carvalho Chehab #include <media/media-device.h>
15238c84f7SMauro Carvalho Chehab #include <media/media-entity.h>
16238c84f7SMauro Carvalho Chehab #include <media/v4l2-device.h>
17238c84f7SMauro Carvalho Chehab #include <media/v4l2-subdev.h>
18238c84f7SMauro Carvalho Chehab #include <media/drv-intf/exynos-fimc.h>
19238c84f7SMauro Carvalho Chehab
20238c84f7SMauro Carvalho Chehab #include "fimc-core.h"
21238c84f7SMauro Carvalho Chehab #include "fimc-lite.h"
22238c84f7SMauro Carvalho Chehab #include "mipi-csis.h"
23238c84f7SMauro Carvalho Chehab
24238c84f7SMauro Carvalho Chehab #define FIMC_OF_NODE_NAME "fimc"
25238c84f7SMauro Carvalho Chehab #define FIMC_LITE_OF_NODE_NAME "fimc-lite"
26238c84f7SMauro Carvalho Chehab #define FIMC_IS_OF_NODE_NAME "fimc-is"
27238c84f7SMauro Carvalho Chehab #define CSIS_OF_NODE_NAME "csis"
28238c84f7SMauro Carvalho Chehab
29238c84f7SMauro Carvalho Chehab #define FIMC_MAX_SENSORS 4
30238c84f7SMauro Carvalho Chehab #define FIMC_MAX_CAMCLKS 2
31238c84f7SMauro Carvalho Chehab #define DEFAULT_SENSOR_CLK_FREQ 24000000U
32238c84f7SMauro Carvalho Chehab
33238c84f7SMauro Carvalho Chehab /* LCD/ISP Writeback clocks (PIXELASYNCMx) */
34238c84f7SMauro Carvalho Chehab enum {
35238c84f7SMauro Carvalho Chehab CLK_IDX_WB_A,
36238c84f7SMauro Carvalho Chehab CLK_IDX_WB_B,
37238c84f7SMauro Carvalho Chehab FIMC_MAX_WBCLKS
38238c84f7SMauro Carvalho Chehab };
39238c84f7SMauro Carvalho Chehab
40238c84f7SMauro Carvalho Chehab enum fimc_subdev_index {
41238c84f7SMauro Carvalho Chehab IDX_SENSOR,
42238c84f7SMauro Carvalho Chehab IDX_CSIS,
43238c84f7SMauro Carvalho Chehab IDX_FLITE,
44238c84f7SMauro Carvalho Chehab IDX_IS_ISP,
45238c84f7SMauro Carvalho Chehab IDX_FIMC,
46238c84f7SMauro Carvalho Chehab IDX_MAX,
47238c84f7SMauro Carvalho Chehab };
48238c84f7SMauro Carvalho Chehab
49238c84f7SMauro Carvalho Chehab /*
50238c84f7SMauro Carvalho Chehab * This structure represents a chain of media entities, including a data
51238c84f7SMauro Carvalho Chehab * source entity (e.g. an image sensor subdevice), a data capture entity
52238c84f7SMauro Carvalho Chehab * - a video capture device node and any remaining entities.
53238c84f7SMauro Carvalho Chehab */
54238c84f7SMauro Carvalho Chehab struct fimc_pipeline {
55238c84f7SMauro Carvalho Chehab struct exynos_media_pipeline ep;
56238c84f7SMauro Carvalho Chehab struct list_head list;
57238c84f7SMauro Carvalho Chehab struct media_entity *vdev_entity;
58238c84f7SMauro Carvalho Chehab struct v4l2_subdev *subdevs[IDX_MAX];
59238c84f7SMauro Carvalho Chehab };
60238c84f7SMauro Carvalho Chehab
61238c84f7SMauro Carvalho Chehab #define to_fimc_pipeline(_ep) container_of(_ep, struct fimc_pipeline, ep)
62238c84f7SMauro Carvalho Chehab
63238c84f7SMauro Carvalho Chehab struct fimc_csis_info {
64238c84f7SMauro Carvalho Chehab struct v4l2_subdev *sd;
65238c84f7SMauro Carvalho Chehab int id;
66238c84f7SMauro Carvalho Chehab };
67238c84f7SMauro Carvalho Chehab
68238c84f7SMauro Carvalho Chehab struct fimc_camclk_info {
69238c84f7SMauro Carvalho Chehab struct clk *clock;
70238c84f7SMauro Carvalho Chehab int use_count;
71238c84f7SMauro Carvalho Chehab unsigned long frequency;
72238c84f7SMauro Carvalho Chehab };
73238c84f7SMauro Carvalho Chehab
74238c84f7SMauro Carvalho Chehab /**
75238c84f7SMauro Carvalho Chehab * struct fimc_sensor_info - image data source subdev information
76238c84f7SMauro Carvalho Chehab * @pdata: sensor's attributes passed as media device's platform data
77238c84f7SMauro Carvalho Chehab * @asd: asynchronous subdev registration data structure
78238c84f7SMauro Carvalho Chehab * @subdev: image sensor v4l2 subdev
79238c84f7SMauro Carvalho Chehab * @host: fimc device the sensor is currently linked to
80238c84f7SMauro Carvalho Chehab *
81238c84f7SMauro Carvalho Chehab * This data structure applies to image sensor and the writeback subdevs.
82238c84f7SMauro Carvalho Chehab */
83238c84f7SMauro Carvalho Chehab struct fimc_sensor_info {
84238c84f7SMauro Carvalho Chehab struct fimc_source_info pdata;
85adb2dcd5SSakari Ailus struct v4l2_async_connection *asd;
86238c84f7SMauro Carvalho Chehab struct v4l2_subdev *subdev;
87238c84f7SMauro Carvalho Chehab struct fimc_dev *host;
88238c84f7SMauro Carvalho Chehab };
89238c84f7SMauro Carvalho Chehab
90238c84f7SMauro Carvalho Chehab struct cam_clk {
91238c84f7SMauro Carvalho Chehab struct clk_hw hw;
92238c84f7SMauro Carvalho Chehab struct fimc_md *fmd;
93238c84f7SMauro Carvalho Chehab };
94238c84f7SMauro Carvalho Chehab #define to_cam_clk(_hw) container_of(_hw, struct cam_clk, hw)
95238c84f7SMauro Carvalho Chehab
96238c84f7SMauro Carvalho Chehab /**
97238c84f7SMauro Carvalho Chehab * struct fimc_md - fimc media device information
98238c84f7SMauro Carvalho Chehab * @csis: MIPI CSIS subdevs data
99238c84f7SMauro Carvalho Chehab * @sensor: array of registered sensor subdevs
100238c84f7SMauro Carvalho Chehab * @num_sensors: actual number of registered sensors
101238c84f7SMauro Carvalho Chehab * @camclk: external sensor clock information
102238c84f7SMauro Carvalho Chehab * @wbclk: external writeback clock information
103238c84f7SMauro Carvalho Chehab * @fimc_lite: array of registered fimc-lite devices
104238c84f7SMauro Carvalho Chehab * @fimc: array of registered fimc devices
105238c84f7SMauro Carvalho Chehab * @fimc_is: fimc-is data structure
106238c84f7SMauro Carvalho Chehab * @use_isp: set to true when FIMC-IS subsystem is used
107238c84f7SMauro Carvalho Chehab * @pmf: handle to the CAMCLK clock control FIMC helper device
108238c84f7SMauro Carvalho Chehab * @media_dev: top level media device
109238c84f7SMauro Carvalho Chehab * @v4l2_dev: top level v4l2_device holding up the subdevs
110238c84f7SMauro Carvalho Chehab * @pdev: platform device this media device is hooked up into
111238c84f7SMauro Carvalho Chehab * @clk_provider: CAMCLK clock provider structure
112238c84f7SMauro Carvalho Chehab * @subdev_notifier: notifier for the subdevs
113238c84f7SMauro Carvalho Chehab * @user_subdev_api: true if subdevs are not configured by the host driver
114238c84f7SMauro Carvalho Chehab * @slock: spinlock protecting @sensor array
115238c84f7SMauro Carvalho Chehab * @pipelines: list of pipelines
116238c84f7SMauro Carvalho Chehab * @link_setup_graph: graph iterator
117238c84f7SMauro Carvalho Chehab */
118238c84f7SMauro Carvalho Chehab struct fimc_md {
119238c84f7SMauro Carvalho Chehab struct fimc_csis_info csis[CSIS_MAX_ENTITIES];
120238c84f7SMauro Carvalho Chehab struct fimc_sensor_info sensor[FIMC_MAX_SENSORS];
121238c84f7SMauro Carvalho Chehab int num_sensors;
122238c84f7SMauro Carvalho Chehab struct fimc_camclk_info camclk[FIMC_MAX_CAMCLKS];
123238c84f7SMauro Carvalho Chehab struct clk *wbclk[FIMC_MAX_WBCLKS];
124238c84f7SMauro Carvalho Chehab struct fimc_lite *fimc_lite[FIMC_LITE_MAX_DEVS];
125238c84f7SMauro Carvalho Chehab struct fimc_dev *fimc[FIMC_MAX_DEVS];
126238c84f7SMauro Carvalho Chehab struct fimc_is *fimc_is;
127238c84f7SMauro Carvalho Chehab bool use_isp;
128238c84f7SMauro Carvalho Chehab struct device *pmf;
129238c84f7SMauro Carvalho Chehab struct media_device media_dev;
130238c84f7SMauro Carvalho Chehab struct v4l2_device v4l2_dev;
131238c84f7SMauro Carvalho Chehab struct platform_device *pdev;
132238c84f7SMauro Carvalho Chehab
133238c84f7SMauro Carvalho Chehab struct cam_clk_provider {
134238c84f7SMauro Carvalho Chehab struct clk *clks[FIMC_MAX_CAMCLKS];
135238c84f7SMauro Carvalho Chehab struct clk_onecell_data clk_data;
136238c84f7SMauro Carvalho Chehab struct device_node *of_node;
137238c84f7SMauro Carvalho Chehab struct cam_clk camclk[FIMC_MAX_CAMCLKS];
138238c84f7SMauro Carvalho Chehab int num_clocks;
139238c84f7SMauro Carvalho Chehab } clk_provider;
140238c84f7SMauro Carvalho Chehab
141238c84f7SMauro Carvalho Chehab struct v4l2_async_notifier subdev_notifier;
142238c84f7SMauro Carvalho Chehab
143238c84f7SMauro Carvalho Chehab bool user_subdev_api;
144238c84f7SMauro Carvalho Chehab spinlock_t slock;
145238c84f7SMauro Carvalho Chehab struct list_head pipelines;
146238c84f7SMauro Carvalho Chehab struct media_graph link_setup_graph;
147238c84f7SMauro Carvalho Chehab };
148238c84f7SMauro Carvalho Chehab
149238c84f7SMauro Carvalho Chehab static inline
source_to_sensor_info(struct fimc_source_info * si)150238c84f7SMauro Carvalho Chehab struct fimc_sensor_info *source_to_sensor_info(struct fimc_source_info *si)
151238c84f7SMauro Carvalho Chehab {
152238c84f7SMauro Carvalho Chehab return container_of(si, struct fimc_sensor_info, pdata);
153238c84f7SMauro Carvalho Chehab }
154238c84f7SMauro Carvalho Chehab
entity_to_fimc_mdev(struct media_entity * me)155238c84f7SMauro Carvalho Chehab static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me)
156238c84f7SMauro Carvalho Chehab {
157238c84f7SMauro Carvalho Chehab return me->graph_obj.mdev == NULL ? NULL :
158238c84f7SMauro Carvalho Chehab container_of(me->graph_obj.mdev, struct fimc_md, media_dev);
159238c84f7SMauro Carvalho Chehab }
160238c84f7SMauro Carvalho Chehab
notifier_to_fimc_md(struct v4l2_async_notifier * n)161238c84f7SMauro Carvalho Chehab static inline struct fimc_md *notifier_to_fimc_md(struct v4l2_async_notifier *n)
162238c84f7SMauro Carvalho Chehab {
163238c84f7SMauro Carvalho Chehab return container_of(n, struct fimc_md, subdev_notifier);
164238c84f7SMauro Carvalho Chehab }
165238c84f7SMauro Carvalho Chehab
fimc_md_graph_lock(struct exynos_video_entity * ve)166238c84f7SMauro Carvalho Chehab static inline void fimc_md_graph_lock(struct exynos_video_entity *ve)
167238c84f7SMauro Carvalho Chehab {
168238c84f7SMauro Carvalho Chehab mutex_lock(&ve->vdev.entity.graph_obj.mdev->graph_mutex);
169238c84f7SMauro Carvalho Chehab }
170238c84f7SMauro Carvalho Chehab
fimc_md_graph_unlock(struct exynos_video_entity * ve)171238c84f7SMauro Carvalho Chehab static inline void fimc_md_graph_unlock(struct exynos_video_entity *ve)
172238c84f7SMauro Carvalho Chehab {
173238c84f7SMauro Carvalho Chehab mutex_unlock(&ve->vdev.entity.graph_obj.mdev->graph_mutex);
174238c84f7SMauro Carvalho Chehab }
175238c84f7SMauro Carvalho Chehab
176238c84f7SMauro Carvalho Chehab int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
177238c84f7SMauro Carvalho Chehab
178238c84f7SMauro Carvalho Chehab #ifdef CONFIG_OF
fimc_md_is_isp_available(struct device_node * node)179238c84f7SMauro Carvalho Chehab static inline bool fimc_md_is_isp_available(struct device_node *node)
180238c84f7SMauro Carvalho Chehab {
181*5262cbf4SJoe Hattori struct device_node *child __free(device_node) =
182*5262cbf4SJoe Hattori of_get_child_by_name(node, FIMC_IS_OF_NODE_NAME);
183*5262cbf4SJoe Hattori return child ? of_device_is_available(child) : false;
184238c84f7SMauro Carvalho Chehab }
185238c84f7SMauro Carvalho Chehab #else
186238c84f7SMauro Carvalho Chehab #define fimc_md_is_isp_available(node) (false)
187238c84f7SMauro Carvalho Chehab #endif /* CONFIG_OF */
188238c84f7SMauro Carvalho Chehab
__fimc_md_get_subdev(struct exynos_media_pipeline * ep,unsigned int index)189238c84f7SMauro Carvalho Chehab static inline struct v4l2_subdev *__fimc_md_get_subdev(
190238c84f7SMauro Carvalho Chehab struct exynos_media_pipeline *ep,
191238c84f7SMauro Carvalho Chehab unsigned int index)
192238c84f7SMauro Carvalho Chehab {
193238c84f7SMauro Carvalho Chehab struct fimc_pipeline *p = to_fimc_pipeline(ep);
194238c84f7SMauro Carvalho Chehab
195238c84f7SMauro Carvalho Chehab if (!p || index >= IDX_MAX)
196238c84f7SMauro Carvalho Chehab return NULL;
197238c84f7SMauro Carvalho Chehab else
198238c84f7SMauro Carvalho Chehab return p->subdevs[index];
199238c84f7SMauro Carvalho Chehab }
200238c84f7SMauro Carvalho Chehab
201238c84f7SMauro Carvalho Chehab #endif
202