1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Rockchip CIF Driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun #include <linux/clk.h>
8*4882a593Smuzhiyun #include <linux/delay.h>
9*4882a593Smuzhiyun #include <linux/interrupt.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/of.h>
12*4882a593Smuzhiyun #include <linux/of_gpio.h>
13*4882a593Smuzhiyun #include <linux/of_graph.h>
14*4882a593Smuzhiyun #include <linux/of_platform.h>
15*4882a593Smuzhiyun #include <linux/of_reserved_mem.h>
16*4882a593Smuzhiyun #include <linux/reset.h>
17*4882a593Smuzhiyun #include <linux/pm_runtime.h>
18*4882a593Smuzhiyun #include <linux/pinctrl/consumer.h>
19*4882a593Smuzhiyun #include <linux/regmap.h>
20*4882a593Smuzhiyun #include <media/videobuf2-dma-contig.h>
21*4882a593Smuzhiyun #include <media/v4l2-fwnode.h>
22*4882a593Smuzhiyun #include "dev.h"
23*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
24*4882a593Smuzhiyun #include <linux/rk-camera-module.h>
25*4882a593Smuzhiyun #include "common.h"
26*4882a593Smuzhiyun
to_sditf_priv(struct v4l2_subdev * subdev)27*4882a593Smuzhiyun static inline struct sditf_priv *to_sditf_priv(struct v4l2_subdev *subdev)
28*4882a593Smuzhiyun {
29*4882a593Smuzhiyun return container_of(subdev, struct sditf_priv, sd);
30*4882a593Smuzhiyun }
31*4882a593Smuzhiyun
sditf_buffree_work(struct work_struct * work)32*4882a593Smuzhiyun static void sditf_buffree_work(struct work_struct *work)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun struct sditf_work_struct *buffree_work = container_of(work,
35*4882a593Smuzhiyun struct sditf_work_struct,
36*4882a593Smuzhiyun work);
37*4882a593Smuzhiyun struct sditf_priv *priv = container_of(buffree_work,
38*4882a593Smuzhiyun struct sditf_priv,
39*4882a593Smuzhiyun buffree_work);
40*4882a593Smuzhiyun struct rkcif_rx_buffer *rx_buf = NULL;
41*4882a593Smuzhiyun unsigned long flags;
42*4882a593Smuzhiyun LIST_HEAD(local_list);
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun spin_lock_irqsave(&priv->cif_dev->buffree_lock, flags);
45*4882a593Smuzhiyun list_replace_init(&priv->buf_free_list, &local_list);
46*4882a593Smuzhiyun while (!list_empty(&local_list)) {
47*4882a593Smuzhiyun rx_buf = list_first_entry(&local_list,
48*4882a593Smuzhiyun struct rkcif_rx_buffer, list_free);
49*4882a593Smuzhiyun if (rx_buf) {
50*4882a593Smuzhiyun list_del(&rx_buf->list_free);
51*4882a593Smuzhiyun rkcif_free_reserved_mem_buf(priv->cif_dev, rx_buf);
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun spin_unlock_irqrestore(&priv->cif_dev->buffree_lock, flags);
55*4882a593Smuzhiyun }
56*4882a593Smuzhiyun
sditf_get_hdr_mode(struct sditf_priv * priv)57*4882a593Smuzhiyun static void sditf_get_hdr_mode(struct sditf_priv *priv)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
60*4882a593Smuzhiyun struct rkmodule_hdr_cfg hdr_cfg;
61*4882a593Smuzhiyun int ret = 0;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun if (!cif_dev->terminal_sensor.sd)
64*4882a593Smuzhiyun rkcif_update_sensor_info(&cif_dev->stream[0]);
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun if (cif_dev->terminal_sensor.sd) {
67*4882a593Smuzhiyun ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd,
68*4882a593Smuzhiyun core, ioctl,
69*4882a593Smuzhiyun RKMODULE_GET_HDR_CFG,
70*4882a593Smuzhiyun &hdr_cfg);
71*4882a593Smuzhiyun if (!ret)
72*4882a593Smuzhiyun priv->hdr_cfg = hdr_cfg;
73*4882a593Smuzhiyun else
74*4882a593Smuzhiyun priv->hdr_cfg.hdr_mode = NO_HDR;
75*4882a593Smuzhiyun } else {
76*4882a593Smuzhiyun priv->hdr_cfg.hdr_mode = NO_HDR;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun
sditf_g_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_frame_interval * fi)80*4882a593Smuzhiyun static int sditf_g_frame_interval(struct v4l2_subdev *sd,
81*4882a593Smuzhiyun struct v4l2_subdev_frame_interval *fi)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun struct sditf_priv *priv = to_sditf_priv(sd);
84*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
85*4882a593Smuzhiyun struct v4l2_subdev *sensor_sd;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun if (!cif_dev->terminal_sensor.sd)
88*4882a593Smuzhiyun rkcif_update_sensor_info(&cif_dev->stream[0]);
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (cif_dev->terminal_sensor.sd) {
91*4882a593Smuzhiyun sensor_sd = cif_dev->terminal_sensor.sd;
92*4882a593Smuzhiyun return v4l2_subdev_call(sensor_sd, video, g_frame_interval, fi);
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun return -EINVAL;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
sditf_g_mbus_config(struct v4l2_subdev * sd,unsigned int pad_id,struct v4l2_mbus_config * config)98*4882a593Smuzhiyun static int sditf_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
99*4882a593Smuzhiyun struct v4l2_mbus_config *config)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun struct sditf_priv *priv = to_sditf_priv(sd);
102*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
103*4882a593Smuzhiyun struct v4l2_subdev *sensor_sd;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun if (!cif_dev->active_sensor)
106*4882a593Smuzhiyun rkcif_update_sensor_info(&cif_dev->stream[0]);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun if (cif_dev->active_sensor) {
109*4882a593Smuzhiyun sensor_sd = cif_dev->active_sensor->sd;
110*4882a593Smuzhiyun return v4l2_subdev_call(sensor_sd, pad, get_mbus_config, 0, config);
111*4882a593Smuzhiyun } else {
112*4882a593Smuzhiyun config->type = V4L2_MBUS_CSI2_DPHY;
113*4882a593Smuzhiyun config->flags = V4L2_MBUS_CSI2_CHANNEL_0 |
114*4882a593Smuzhiyun V4L2_MBUS_CSI2_CONTINUOUS_CLOCK;
115*4882a593Smuzhiyun return 0;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun return -EINVAL;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
sditf_get_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)121*4882a593Smuzhiyun static int sditf_get_set_fmt(struct v4l2_subdev *sd,
122*4882a593Smuzhiyun struct v4l2_subdev_pad_config *cfg,
123*4882a593Smuzhiyun struct v4l2_subdev_format *fmt)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun struct sditf_priv *priv = to_sditf_priv(sd);
126*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
127*4882a593Smuzhiyun struct v4l2_subdev_selection input_sel;
128*4882a593Smuzhiyun struct v4l2_pix_format_mplane pixm;
129*4882a593Smuzhiyun const struct cif_output_fmt *out_fmt;
130*4882a593Smuzhiyun int ret = -EINVAL;
131*4882a593Smuzhiyun bool is_uncompact = false;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun if (!cif_dev->terminal_sensor.sd)
134*4882a593Smuzhiyun rkcif_update_sensor_info(&cif_dev->stream[0]);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun if (cif_dev->terminal_sensor.sd) {
137*4882a593Smuzhiyun sditf_get_hdr_mode(priv);
138*4882a593Smuzhiyun fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
139*4882a593Smuzhiyun fmt->pad = 0;
140*4882a593Smuzhiyun ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd, pad, get_fmt, NULL, fmt);
141*4882a593Smuzhiyun if (ret) {
142*4882a593Smuzhiyun v4l2_err(&priv->sd,
143*4882a593Smuzhiyun "%s: get sensor format failed\n", __func__);
144*4882a593Smuzhiyun return ret;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun input_sel.target = V4L2_SEL_TGT_CROP_BOUNDS;
148*4882a593Smuzhiyun input_sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
149*4882a593Smuzhiyun input_sel.pad = 0;
150*4882a593Smuzhiyun ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd,
151*4882a593Smuzhiyun pad, get_selection, NULL,
152*4882a593Smuzhiyun &input_sel);
153*4882a593Smuzhiyun if (!ret) {
154*4882a593Smuzhiyun fmt->format.width = input_sel.r.width;
155*4882a593Smuzhiyun fmt->format.height = input_sel.r.height;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun priv->cap_info.width = fmt->format.width;
158*4882a593Smuzhiyun priv->cap_info.height = fmt->format.height;
159*4882a593Smuzhiyun pixm.pixelformat = rkcif_mbus_pixelcode_to_v4l2(fmt->format.code);
160*4882a593Smuzhiyun pixm.width = priv->cap_info.width;
161*4882a593Smuzhiyun pixm.height = priv->cap_info.height;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun out_fmt = rkcif_find_output_fmt(NULL, pixm.pixelformat);
164*4882a593Smuzhiyun if (priv->toisp_inf.link_mode == TOISP_UNITE &&
165*4882a593Smuzhiyun ((pixm.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL) * out_fmt->raw_bpp / 8) & 0xf)
166*4882a593Smuzhiyun is_uncompact = true;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
169*4882a593Smuzhiyun "%s, width %d, height %d, hdr mode %d\n",
170*4882a593Smuzhiyun __func__, fmt->format.width, fmt->format.height, priv->hdr_cfg.hdr_mode);
171*4882a593Smuzhiyun if (priv->hdr_cfg.hdr_mode == NO_HDR ||
172*4882a593Smuzhiyun priv->hdr_cfg.hdr_mode == HDR_COMPR) {
173*4882a593Smuzhiyun rkcif_set_fmt(&cif_dev->stream[0], &pixm, false);
174*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
175*4882a593Smuzhiyun if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE &&
176*4882a593Smuzhiyun priv->toisp_inf.link_mode == TOISP_UNITE) {
177*4882a593Smuzhiyun if (is_uncompact) {
178*4882a593Smuzhiyun cif_dev->stream[0].is_compact = false;
179*4882a593Smuzhiyun cif_dev->stream[0].is_high_align = true;
180*4882a593Smuzhiyun } else {
181*4882a593Smuzhiyun cif_dev->stream[0].is_compact = true;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun rkcif_set_fmt(&cif_dev->stream[0], &pixm, false);
185*4882a593Smuzhiyun rkcif_set_fmt(&cif_dev->stream[1], &pixm, false);
186*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
187*4882a593Smuzhiyun if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE &&
188*4882a593Smuzhiyun priv->toisp_inf.link_mode == TOISP_UNITE) {
189*4882a593Smuzhiyun if (is_uncompact) {
190*4882a593Smuzhiyun cif_dev->stream[0].is_compact = false;
191*4882a593Smuzhiyun cif_dev->stream[0].is_high_align = true;
192*4882a593Smuzhiyun cif_dev->stream[1].is_compact = false;
193*4882a593Smuzhiyun cif_dev->stream[1].is_high_align = true;
194*4882a593Smuzhiyun } else {
195*4882a593Smuzhiyun cif_dev->stream[0].is_compact = true;
196*4882a593Smuzhiyun cif_dev->stream[1].is_compact = true;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun rkcif_set_fmt(&cif_dev->stream[0], &pixm, false);
200*4882a593Smuzhiyun rkcif_set_fmt(&cif_dev->stream[1], &pixm, false);
201*4882a593Smuzhiyun rkcif_set_fmt(&cif_dev->stream[2], &pixm, false);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun } else {
204*4882a593Smuzhiyun if (priv->sensor_sd) {
205*4882a593Smuzhiyun fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
206*4882a593Smuzhiyun fmt->pad = 0;
207*4882a593Smuzhiyun ret = v4l2_subdev_call(priv->sensor_sd, pad, get_fmt, NULL, fmt);
208*4882a593Smuzhiyun if (ret) {
209*4882a593Smuzhiyun v4l2_err(&priv->sd,
210*4882a593Smuzhiyun "%s: get sensor format failed\n", __func__);
211*4882a593Smuzhiyun return ret;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun input_sel.target = V4L2_SEL_TGT_CROP_BOUNDS;
215*4882a593Smuzhiyun input_sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
216*4882a593Smuzhiyun input_sel.pad = 0;
217*4882a593Smuzhiyun ret = v4l2_subdev_call(priv->sensor_sd,
218*4882a593Smuzhiyun pad, get_selection, NULL,
219*4882a593Smuzhiyun &input_sel);
220*4882a593Smuzhiyun if (!ret) {
221*4882a593Smuzhiyun fmt->format.width = input_sel.r.width;
222*4882a593Smuzhiyun fmt->format.height = input_sel.r.height;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun priv->cap_info.width = fmt->format.width;
225*4882a593Smuzhiyun priv->cap_info.height = fmt->format.height;
226*4882a593Smuzhiyun pixm.pixelformat = rkcif_mbus_pixelcode_to_v4l2(fmt->format.code);
227*4882a593Smuzhiyun pixm.width = priv->cap_info.width;
228*4882a593Smuzhiyun pixm.height = priv->cap_info.height;
229*4882a593Smuzhiyun } else {
230*4882a593Smuzhiyun fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
231*4882a593Smuzhiyun fmt->pad = 0;
232*4882a593Smuzhiyun fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
233*4882a593Smuzhiyun fmt->format.width = 640;
234*4882a593Smuzhiyun fmt->format.height = 480;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun return 0;
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
sditf_init_buf(struct sditf_priv * priv)241*4882a593Smuzhiyun static int sditf_init_buf(struct sditf_priv *priv)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
244*4882a593Smuzhiyun int ret = 0;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun if (priv->hdr_cfg.hdr_mode == HDR_X2) {
247*4882a593Smuzhiyun if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) {
248*4882a593Smuzhiyun if (cif_dev->is_thunderboot)
249*4882a593Smuzhiyun cif_dev->resmem_size /= 2;
250*4882a593Smuzhiyun ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
251*4882a593Smuzhiyun if (cif_dev->is_thunderboot)
252*4882a593Smuzhiyun cif_dev->resmem_pa += cif_dev->resmem_size;
253*4882a593Smuzhiyun ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num);
254*4882a593Smuzhiyun } else {
255*4882a593Smuzhiyun ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
258*4882a593Smuzhiyun if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) {
259*4882a593Smuzhiyun if (cif_dev->is_thunderboot)
260*4882a593Smuzhiyun cif_dev->resmem_size /= 3;
261*4882a593Smuzhiyun ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
262*4882a593Smuzhiyun if (cif_dev->is_thunderboot)
263*4882a593Smuzhiyun cif_dev->resmem_pa += cif_dev->resmem_size;
264*4882a593Smuzhiyun ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num);
265*4882a593Smuzhiyun if (cif_dev->is_thunderboot)
266*4882a593Smuzhiyun cif_dev->resmem_pa += cif_dev->resmem_size;
267*4882a593Smuzhiyun ret |= rkcif_init_rx_buf(&cif_dev->stream[2], priv->buf_num);
268*4882a593Smuzhiyun } else {
269*4882a593Smuzhiyun ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
270*4882a593Smuzhiyun ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num);
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun } else {
273*4882a593Smuzhiyun if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO)
274*4882a593Smuzhiyun ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
275*4882a593Smuzhiyun else
276*4882a593Smuzhiyun ret = -EINVAL;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun return ret;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
sditf_free_buf(struct sditf_priv * priv)281*4882a593Smuzhiyun static void sditf_free_buf(struct sditf_priv *priv)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun if (priv->hdr_cfg.hdr_mode == HDR_X2) {
286*4882a593Smuzhiyun rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
287*4882a593Smuzhiyun rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num);
288*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
289*4882a593Smuzhiyun rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
290*4882a593Smuzhiyun rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num);
291*4882a593Smuzhiyun rkcif_free_rx_buf(&cif_dev->stream[2], priv->buf_num);
292*4882a593Smuzhiyun } else {
293*4882a593Smuzhiyun rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun if (cif_dev->is_thunderboot) {
296*4882a593Smuzhiyun cif_dev->wait_line_cache = 0;
297*4882a593Smuzhiyun cif_dev->wait_line = 0;
298*4882a593Smuzhiyun cif_dev->wait_line_bak = 0;
299*4882a593Smuzhiyun cif_dev->is_thunderboot = false;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
sditf_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_selection * sel)303*4882a593Smuzhiyun static int sditf_get_selection(struct v4l2_subdev *sd,
304*4882a593Smuzhiyun struct v4l2_subdev_pad_config *cfg,
305*4882a593Smuzhiyun struct v4l2_subdev_selection *sel)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun return -EINVAL;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
sditf_reinit_mode(struct sditf_priv * priv,struct rkisp_vicap_mode * mode)310*4882a593Smuzhiyun static void sditf_reinit_mode(struct sditf_priv *priv, struct rkisp_vicap_mode *mode)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun if (mode->rdbk_mode == RKISP_VICAP_RDBK_AIQ) {
313*4882a593Smuzhiyun priv->toisp_inf.link_mode = TOISP_NONE;
314*4882a593Smuzhiyun } else {
315*4882a593Smuzhiyun if (strstr(mode->name, RKISP0_DEVNAME))
316*4882a593Smuzhiyun priv->toisp_inf.link_mode = TOISP0;
317*4882a593Smuzhiyun else if (strstr(mode->name, RKISP1_DEVNAME))
318*4882a593Smuzhiyun priv->toisp_inf.link_mode = TOISP1;
319*4882a593Smuzhiyun else if (strstr(mode->name, RKISP_UNITE_DEVNAME))
320*4882a593Smuzhiyun priv->toisp_inf.link_mode = TOISP_UNITE;
321*4882a593Smuzhiyun else
322*4882a593Smuzhiyun priv->toisp_inf.link_mode = TOISP0;
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun v4l2_dbg(1, rkcif_debug, &priv->cif_dev->v4l2_dev,
326*4882a593Smuzhiyun "%s, mode->rdbk_mode %d, mode->name %s, link_mode %d\n",
327*4882a593Smuzhiyun __func__, mode->rdbk_mode, mode->name, priv->toisp_inf.link_mode);
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun
sditf_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)330*4882a593Smuzhiyun static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun struct sditf_priv *priv = to_sditf_priv(sd);
333*4882a593Smuzhiyun struct rkisp_vicap_mode *mode;
334*4882a593Smuzhiyun struct v4l2_subdev_format fmt;
335*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
336*4882a593Smuzhiyun struct v4l2_subdev *sensor_sd;
337*4882a593Smuzhiyun int *pbuf_num = NULL;
338*4882a593Smuzhiyun int ret = 0;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun switch (cmd) {
341*4882a593Smuzhiyun case RKISP_VICAP_CMD_MODE:
342*4882a593Smuzhiyun mode = (struct rkisp_vicap_mode *)arg;
343*4882a593Smuzhiyun memcpy(&priv->mode, mode, sizeof(*mode));
344*4882a593Smuzhiyun sditf_reinit_mode(priv, &priv->mode);
345*4882a593Smuzhiyun if (priv->is_combine_mode)
346*4882a593Smuzhiyun mode->input.merge_num = cif_dev->sditf_cnt;
347*4882a593Smuzhiyun else
348*4882a593Smuzhiyun mode->input.merge_num = 1;
349*4882a593Smuzhiyun mode->input.index = priv->combine_index;
350*4882a593Smuzhiyun return 0;
351*4882a593Smuzhiyun case RKISP_VICAP_CMD_INIT_BUF:
352*4882a593Smuzhiyun pbuf_num = (int *)arg;
353*4882a593Smuzhiyun priv->buf_num = *pbuf_num;
354*4882a593Smuzhiyun sditf_get_set_fmt(&priv->sd, NULL, &fmt);
355*4882a593Smuzhiyun ret = sditf_init_buf(priv);
356*4882a593Smuzhiyun return ret;
357*4882a593Smuzhiyun case RKMODULE_GET_HDR_CFG:
358*4882a593Smuzhiyun if (!cif_dev->terminal_sensor.sd)
359*4882a593Smuzhiyun rkcif_update_sensor_info(&cif_dev->stream[0]);
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun if (cif_dev->terminal_sensor.sd) {
362*4882a593Smuzhiyun sensor_sd = cif_dev->terminal_sensor.sd;
363*4882a593Smuzhiyun return v4l2_subdev_call(sensor_sd, core, ioctl, cmd, arg);
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun break;
366*4882a593Smuzhiyun default:
367*4882a593Smuzhiyun break;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun return -EINVAL;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
sditf_compat_ioctl32(struct v4l2_subdev * sd,unsigned int cmd,unsigned long arg)374*4882a593Smuzhiyun static long sditf_compat_ioctl32(struct v4l2_subdev *sd,
375*4882a593Smuzhiyun unsigned int cmd, unsigned long arg)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun void __user *up = compat_ptr(arg);
378*4882a593Smuzhiyun struct sditf_priv *priv = to_sditf_priv(sd);
379*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
380*4882a593Smuzhiyun struct v4l2_subdev *sensor_sd;
381*4882a593Smuzhiyun struct rkisp_vicap_mode *mode;
382*4882a593Smuzhiyun struct rkmodule_hdr_cfg *hdr_cfg;
383*4882a593Smuzhiyun int buf_num;
384*4882a593Smuzhiyun int ret = 0;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun switch (cmd) {
387*4882a593Smuzhiyun case RKISP_VICAP_CMD_MODE:
388*4882a593Smuzhiyun mode = kzalloc(sizeof(*mode), GFP_KERNEL);
389*4882a593Smuzhiyun if (!mode) {
390*4882a593Smuzhiyun ret = -ENOMEM;
391*4882a593Smuzhiyun return ret;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun if (copy_from_user(mode, up, sizeof(*mode))) {
394*4882a593Smuzhiyun kfree(mode);
395*4882a593Smuzhiyun return -EFAULT;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun ret = sditf_ioctl(sd, cmd, mode);
398*4882a593Smuzhiyun kfree(mode);
399*4882a593Smuzhiyun return ret;
400*4882a593Smuzhiyun case RKISP_VICAP_CMD_INIT_BUF:
401*4882a593Smuzhiyun if (copy_from_user(&buf_num, up, sizeof(int)))
402*4882a593Smuzhiyun return -EFAULT;
403*4882a593Smuzhiyun ret = sditf_ioctl(sd, cmd, &buf_num);
404*4882a593Smuzhiyun return ret;
405*4882a593Smuzhiyun case RKMODULE_GET_HDR_CFG:
406*4882a593Smuzhiyun hdr_cfg = kzalloc(sizeof(*hdr_cfg), GFP_KERNEL);
407*4882a593Smuzhiyun if (!hdr_cfg) {
408*4882a593Smuzhiyun ret = -ENOMEM;
409*4882a593Smuzhiyun return ret;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun if (copy_from_user(hdr_cfg, up, sizeof(*hdr_cfg))) {
412*4882a593Smuzhiyun kfree(hdr_cfg);
413*4882a593Smuzhiyun return -EFAULT;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun ret = sditf_ioctl(sd, cmd, hdr_cfg);
416*4882a593Smuzhiyun return ret;
417*4882a593Smuzhiyun default:
418*4882a593Smuzhiyun break;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun if (!cif_dev->terminal_sensor.sd)
422*4882a593Smuzhiyun rkcif_update_sensor_info(&cif_dev->stream[0]);
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun if (cif_dev->terminal_sensor.sd) {
425*4882a593Smuzhiyun sensor_sd = cif_dev->terminal_sensor.sd;
426*4882a593Smuzhiyun return v4l2_subdev_call(sensor_sd, core, compat_ioctl32, cmd, arg);
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun return -EINVAL;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun #endif
432*4882a593Smuzhiyun
sditf_channel_enable(struct sditf_priv * priv,int user)433*4882a593Smuzhiyun static int sditf_channel_enable(struct sditf_priv *priv, int user)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
436*4882a593Smuzhiyun struct rkmodule_capture_info *capture_info = &cif_dev->channels[0].capture_info;
437*4882a593Smuzhiyun unsigned int ch0 = 0, ch1 = 0, ch2 = 0;
438*4882a593Smuzhiyun unsigned int ctrl_val = 0;
439*4882a593Smuzhiyun unsigned int int_en = 0;
440*4882a593Smuzhiyun unsigned int offset_x = 0;
441*4882a593Smuzhiyun unsigned int offset_y = 0;
442*4882a593Smuzhiyun unsigned int width = priv->cap_info.width;
443*4882a593Smuzhiyun unsigned int height = priv->cap_info.height;
444*4882a593Smuzhiyun int csi_idx = cif_dev->csi_host_idx;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE &&
447*4882a593Smuzhiyun priv->toisp_inf.link_mode == TOISP_UNITE) {
448*4882a593Smuzhiyun if (capture_info->multi_dev.dev_num != 2 ||
449*4882a593Smuzhiyun capture_info->multi_dev.pixel_offset != RKMOUDLE_UNITE_EXTEND_PIXEL) {
450*4882a593Smuzhiyun v4l2_err(&cif_dev->v4l2_dev,
451*4882a593Smuzhiyun "param error of online mode, combine dev num %d, offset %d\n",
452*4882a593Smuzhiyun capture_info->multi_dev.dev_num,
453*4882a593Smuzhiyun capture_info->multi_dev.pixel_offset);
454*4882a593Smuzhiyun return -EINVAL;
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun csi_idx = capture_info->multi_dev.dev_idx[user];
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun if (priv->hdr_cfg.hdr_mode == NO_HDR ||
460*4882a593Smuzhiyun priv->hdr_cfg.hdr_mode == HDR_COMPR) {
461*4882a593Smuzhiyun if (cif_dev->inf_id == RKCIF_MIPI_LVDS)
462*4882a593Smuzhiyun ch0 = csi_idx * 4;
463*4882a593Smuzhiyun else
464*4882a593Smuzhiyun ch0 = 24;//dvp
465*4882a593Smuzhiyun ctrl_val = (ch0 << 3) | 0x1;
466*4882a593Smuzhiyun if (user == 0)
467*4882a593Smuzhiyun int_en = CIF_TOISP0_FS(0);
468*4882a593Smuzhiyun else
469*4882a593Smuzhiyun int_en = CIF_TOISP1_FS(0);
470*4882a593Smuzhiyun priv->toisp_inf.ch_info[0].is_valid = true;
471*4882a593Smuzhiyun priv->toisp_inf.ch_info[0].id = ch0;
472*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
473*4882a593Smuzhiyun ch0 = cif_dev->csi_host_idx * 4 + 1;
474*4882a593Smuzhiyun ch1 = cif_dev->csi_host_idx * 4;
475*4882a593Smuzhiyun ctrl_val = (ch0 << 3) | 0x1;
476*4882a593Smuzhiyun ctrl_val |= (ch1 << 11) | 0x100;
477*4882a593Smuzhiyun if (user == 0)
478*4882a593Smuzhiyun int_en = CIF_TOISP0_FS(0) | CIF_TOISP0_FS(1);
479*4882a593Smuzhiyun else
480*4882a593Smuzhiyun int_en = CIF_TOISP1_FS(0) | CIF_TOISP1_FS(1);
481*4882a593Smuzhiyun priv->toisp_inf.ch_info[0].is_valid = true;
482*4882a593Smuzhiyun priv->toisp_inf.ch_info[0].id = ch0;
483*4882a593Smuzhiyun priv->toisp_inf.ch_info[1].is_valid = true;
484*4882a593Smuzhiyun priv->toisp_inf.ch_info[1].id = ch1;
485*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
486*4882a593Smuzhiyun ch0 = cif_dev->csi_host_idx * 4 + 2;
487*4882a593Smuzhiyun ch1 = cif_dev->csi_host_idx * 4 + 1;
488*4882a593Smuzhiyun ch2 = cif_dev->csi_host_idx * 4;
489*4882a593Smuzhiyun ctrl_val = (ch0 << 3) | 0x1;
490*4882a593Smuzhiyun ctrl_val |= (ch1 << 11) | 0x100;
491*4882a593Smuzhiyun ctrl_val |= (ch2 << 19) | 0x10000;
492*4882a593Smuzhiyun if (user == 0)
493*4882a593Smuzhiyun int_en = CIF_TOISP0_FS(0) | CIF_TOISP0_FS(1) | CIF_TOISP0_FS(2);
494*4882a593Smuzhiyun else
495*4882a593Smuzhiyun int_en = CIF_TOISP1_FS(0) | CIF_TOISP1_FS(1) | CIF_TOISP1_FS(2);
496*4882a593Smuzhiyun priv->toisp_inf.ch_info[0].is_valid = true;
497*4882a593Smuzhiyun priv->toisp_inf.ch_info[0].id = ch0;
498*4882a593Smuzhiyun priv->toisp_inf.ch_info[1].is_valid = true;
499*4882a593Smuzhiyun priv->toisp_inf.ch_info[1].id = ch1;
500*4882a593Smuzhiyun priv->toisp_inf.ch_info[2].is_valid = true;
501*4882a593Smuzhiyun priv->toisp_inf.ch_info[2].id = ch2;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun if (user == 0) {
504*4882a593Smuzhiyun if (priv->toisp_inf.link_mode == TOISP_UNITE)
505*4882a593Smuzhiyun width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
506*4882a593Smuzhiyun rkcif_write_register(cif_dev, CIF_REG_TOISP0_CTRL, ctrl_val);
507*4882a593Smuzhiyun if (width && height) {
508*4882a593Smuzhiyun rkcif_write_register(cif_dev, CIF_REG_TOISP0_CROP,
509*4882a593Smuzhiyun offset_x | (offset_y << 16));
510*4882a593Smuzhiyun rkcif_write_register(cif_dev, CIF_REG_TOISP0_SIZE,
511*4882a593Smuzhiyun width | (height << 16));
512*4882a593Smuzhiyun } else {
513*4882a593Smuzhiyun return -EINVAL;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun } else {
516*4882a593Smuzhiyun if (priv->toisp_inf.link_mode == TOISP_UNITE) {
517*4882a593Smuzhiyun if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE)
518*4882a593Smuzhiyun offset_x = 0;
519*4882a593Smuzhiyun else
520*4882a593Smuzhiyun offset_x = priv->cap_info.width / 2 - RKMOUDLE_UNITE_EXTEND_PIXEL;
521*4882a593Smuzhiyun width = priv->cap_info.width / 2 + RKMOUDLE_UNITE_EXTEND_PIXEL;
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun rkcif_write_register(cif_dev, CIF_REG_TOISP1_CTRL, ctrl_val);
524*4882a593Smuzhiyun if (width && height) {
525*4882a593Smuzhiyun rkcif_write_register(cif_dev, CIF_REG_TOISP1_CROP,
526*4882a593Smuzhiyun offset_x | (offset_y << 16));
527*4882a593Smuzhiyun rkcif_write_register(cif_dev, CIF_REG_TOISP1_SIZE,
528*4882a593Smuzhiyun width | (height << 16));
529*4882a593Smuzhiyun } else {
530*4882a593Smuzhiyun return -EINVAL;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_CPU_RV1106)
534*4882a593Smuzhiyun rv1106_sdmmc_get_lock();
535*4882a593Smuzhiyun #endif
536*4882a593Smuzhiyun rkcif_write_register_or(cif_dev, CIF_REG_GLB_INTEN, int_en);
537*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_CPU_RV1106)
538*4882a593Smuzhiyun rv1106_sdmmc_put_lock();
539*4882a593Smuzhiyun #endif
540*4882a593Smuzhiyun return 0;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
sditf_channel_disable(struct sditf_priv * priv,int user)543*4882a593Smuzhiyun static void sditf_channel_disable(struct sditf_priv *priv, int user)
544*4882a593Smuzhiyun {
545*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
546*4882a593Smuzhiyun unsigned int ctrl_val = 0;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun if (priv->hdr_cfg.hdr_mode == NO_HDR ||
549*4882a593Smuzhiyun priv->hdr_cfg.hdr_mode == HDR_COMPR) {
550*4882a593Smuzhiyun if (user == 0)
551*4882a593Smuzhiyun ctrl_val = CIF_TOISP0_FE(0);
552*4882a593Smuzhiyun else
553*4882a593Smuzhiyun ctrl_val = CIF_TOISP1_FE(0);
554*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
555*4882a593Smuzhiyun if (user == 0)
556*4882a593Smuzhiyun ctrl_val = CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1);
557*4882a593Smuzhiyun else
558*4882a593Smuzhiyun ctrl_val = CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1);
559*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
560*4882a593Smuzhiyun if (user == 0)
561*4882a593Smuzhiyun ctrl_val = CIF_TOISP0_FE(0) | CIF_TOISP0_FE(1) | CIF_TOISP0_FE(2);
562*4882a593Smuzhiyun else
563*4882a593Smuzhiyun ctrl_val = CIF_TOISP1_FE(0) | CIF_TOISP1_FE(1) | CIF_TOISP1_FE(2);
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_CPU_RV1106)
566*4882a593Smuzhiyun rv1106_sdmmc_get_lock();
567*4882a593Smuzhiyun #endif
568*4882a593Smuzhiyun rkcif_write_register_or(cif_dev, CIF_REG_GLB_INTEN, ctrl_val);
569*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_CPU_RV1106)
570*4882a593Smuzhiyun rv1106_sdmmc_put_lock();
571*4882a593Smuzhiyun #endif
572*4882a593Smuzhiyun priv->toisp_inf.ch_info[0].is_valid = false;
573*4882a593Smuzhiyun priv->toisp_inf.ch_info[1].is_valid = false;
574*4882a593Smuzhiyun priv->toisp_inf.ch_info[2].is_valid = false;
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
sditf_change_to_online(struct sditf_priv * priv)577*4882a593Smuzhiyun void sditf_change_to_online(struct sditf_priv *priv)
578*4882a593Smuzhiyun {
579*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun priv->mode.rdbk_mode = RKISP_VICAP_ONLINE;
582*4882a593Smuzhiyun if (priv->toisp_inf.link_mode == TOISP0) {
583*4882a593Smuzhiyun sditf_channel_enable(priv, 0);
584*4882a593Smuzhiyun } else if (priv->toisp_inf.link_mode == TOISP1) {
585*4882a593Smuzhiyun sditf_channel_enable(priv, 1);
586*4882a593Smuzhiyun } else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
587*4882a593Smuzhiyun sditf_channel_enable(priv, 0);
588*4882a593Smuzhiyun sditf_channel_enable(priv, 1);
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun if (priv->hdr_cfg.hdr_mode == NO_HDR) {
591*4882a593Smuzhiyun rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
592*4882a593Smuzhiyun cif_dev->stream[0].is_line_wake_up = false;
593*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
594*4882a593Smuzhiyun rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num);
595*4882a593Smuzhiyun cif_dev->stream[0].is_line_wake_up = false;
596*4882a593Smuzhiyun cif_dev->stream[1].is_line_wake_up = false;
597*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
598*4882a593Smuzhiyun rkcif_free_rx_buf(&cif_dev->stream[2], priv->buf_num);
599*4882a593Smuzhiyun cif_dev->stream[0].is_line_wake_up = false;
600*4882a593Smuzhiyun cif_dev->stream[1].is_line_wake_up = false;
601*4882a593Smuzhiyun cif_dev->stream[2].is_line_wake_up = false;
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun cif_dev->wait_line_cache = 0;
604*4882a593Smuzhiyun cif_dev->wait_line = 0;
605*4882a593Smuzhiyun cif_dev->wait_line_bak = 0;
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun
sditf_check_capture_mode(struct rkcif_device * cif_dev)608*4882a593Smuzhiyun static void sditf_check_capture_mode(struct rkcif_device *cif_dev)
609*4882a593Smuzhiyun {
610*4882a593Smuzhiyun struct rkcif_device *dev = NULL;
611*4882a593Smuzhiyun int i = 0;
612*4882a593Smuzhiyun int toisp_cnt = 0;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun for (i = 0; i < cif_dev->hw_dev->dev_num; i++) {
615*4882a593Smuzhiyun dev = cif_dev->hw_dev->cif_dev[i];
616*4882a593Smuzhiyun if (dev && dev->sditf_cnt)
617*4882a593Smuzhiyun toisp_cnt++;
618*4882a593Smuzhiyun }
619*4882a593Smuzhiyun if (cif_dev->is_thunderboot && toisp_cnt == 1)
620*4882a593Smuzhiyun cif_dev->is_rdbk_to_online = true;
621*4882a593Smuzhiyun else
622*4882a593Smuzhiyun cif_dev->is_rdbk_to_online = false;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun
sditf_start_stream(struct sditf_priv * priv)625*4882a593Smuzhiyun static int sditf_start_stream(struct sditf_priv *priv)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
628*4882a593Smuzhiyun struct v4l2_subdev_format fmt;
629*4882a593Smuzhiyun unsigned int mode = RKCIF_STREAM_MODE_TOISP;
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun sditf_check_capture_mode(cif_dev);
632*4882a593Smuzhiyun sditf_get_set_fmt(&priv->sd, NULL, &fmt);
633*4882a593Smuzhiyun if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE) {
634*4882a593Smuzhiyun if (priv->toisp_inf.link_mode == TOISP0) {
635*4882a593Smuzhiyun sditf_channel_enable(priv, 0);
636*4882a593Smuzhiyun } else if (priv->toisp_inf.link_mode == TOISP1) {
637*4882a593Smuzhiyun sditf_channel_enable(priv, 1);
638*4882a593Smuzhiyun } else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
639*4882a593Smuzhiyun sditf_channel_enable(priv, 0);
640*4882a593Smuzhiyun sditf_channel_enable(priv, 1);
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun mode = RKCIF_STREAM_MODE_TOISP;
643*4882a593Smuzhiyun } else if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO) {
644*4882a593Smuzhiyun mode = RKCIF_STREAM_MODE_TOISP_RDBK;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun if (priv->hdr_cfg.hdr_mode == NO_HDR ||
648*4882a593Smuzhiyun priv->hdr_cfg.hdr_mode == HDR_COMPR) {
649*4882a593Smuzhiyun rkcif_do_start_stream(&cif_dev->stream[0], mode);
650*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
651*4882a593Smuzhiyun rkcif_do_start_stream(&cif_dev->stream[0], mode);
652*4882a593Smuzhiyun rkcif_do_start_stream(&cif_dev->stream[1], mode);
653*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
654*4882a593Smuzhiyun rkcif_do_start_stream(&cif_dev->stream[0], mode);
655*4882a593Smuzhiyun rkcif_do_start_stream(&cif_dev->stream[1], mode);
656*4882a593Smuzhiyun rkcif_do_start_stream(&cif_dev->stream[2], mode);
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun INIT_LIST_HEAD(&priv->buf_free_list);
659*4882a593Smuzhiyun return 0;
660*4882a593Smuzhiyun }
661*4882a593Smuzhiyun
sditf_stop_stream(struct sditf_priv * priv)662*4882a593Smuzhiyun static int sditf_stop_stream(struct sditf_priv *priv)
663*4882a593Smuzhiyun {
664*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
665*4882a593Smuzhiyun unsigned int mode = RKCIF_STREAM_MODE_TOISP;
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun if (priv->toisp_inf.link_mode == TOISP0) {
668*4882a593Smuzhiyun sditf_channel_disable(priv, 0);
669*4882a593Smuzhiyun } else if (priv->toisp_inf.link_mode == TOISP1) {
670*4882a593Smuzhiyun sditf_channel_disable(priv, 1);
671*4882a593Smuzhiyun } else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
672*4882a593Smuzhiyun sditf_channel_disable(priv, 0);
673*4882a593Smuzhiyun sditf_channel_disable(priv, 1);
674*4882a593Smuzhiyun }
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun if (priv->mode.rdbk_mode == RKISP_VICAP_ONLINE)
677*4882a593Smuzhiyun mode = RKCIF_STREAM_MODE_TOISP;
678*4882a593Smuzhiyun else if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AUTO)
679*4882a593Smuzhiyun mode = RKCIF_STREAM_MODE_TOISP_RDBK;
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun if (priv->hdr_cfg.hdr_mode == NO_HDR ||
682*4882a593Smuzhiyun priv->hdr_cfg.hdr_mode == HDR_COMPR) {
683*4882a593Smuzhiyun rkcif_do_stop_stream(&cif_dev->stream[0], mode);
684*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
685*4882a593Smuzhiyun rkcif_do_stop_stream(&cif_dev->stream[0], mode);
686*4882a593Smuzhiyun rkcif_do_stop_stream(&cif_dev->stream[1], mode);
687*4882a593Smuzhiyun } else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
688*4882a593Smuzhiyun rkcif_do_stop_stream(&cif_dev->stream[0], mode);
689*4882a593Smuzhiyun rkcif_do_stop_stream(&cif_dev->stream[1], mode);
690*4882a593Smuzhiyun rkcif_do_stop_stream(&cif_dev->stream[2], mode);
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun return 0;
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun
sditf_s_stream(struct v4l2_subdev * sd,int on)695*4882a593Smuzhiyun static int sditf_s_stream(struct v4l2_subdev *sd, int on)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun struct sditf_priv *priv = to_sditf_priv(sd);
698*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
699*4882a593Smuzhiyun int ret = 0;
700*4882a593Smuzhiyun
701*4882a593Smuzhiyun if (!on && atomic_dec_return(&priv->stream_cnt))
702*4882a593Smuzhiyun return 0;
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun if (on && atomic_inc_return(&priv->stream_cnt) > 1)
705*4882a593Smuzhiyun return 0;
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
708*4882a593Smuzhiyun if (priv->mode.rdbk_mode == RKISP_VICAP_RDBK_AIQ)
709*4882a593Smuzhiyun return 0;
710*4882a593Smuzhiyun v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
711*4882a593Smuzhiyun "%s, toisp mode %d, hdr %d, stream on %d\n",
712*4882a593Smuzhiyun __func__, priv->toisp_inf.link_mode, priv->hdr_cfg.hdr_mode, on);
713*4882a593Smuzhiyun if (on) {
714*4882a593Smuzhiyun ret = sditf_start_stream(priv);
715*4882a593Smuzhiyun } else {
716*4882a593Smuzhiyun ret = sditf_stop_stream(priv);
717*4882a593Smuzhiyun sditf_free_buf(priv);
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun
720*4882a593Smuzhiyun }
721*4882a593Smuzhiyun return ret;
722*4882a593Smuzhiyun }
723*4882a593Smuzhiyun
sditf_s_power(struct v4l2_subdev * sd,int on)724*4882a593Smuzhiyun static int sditf_s_power(struct v4l2_subdev *sd, int on)
725*4882a593Smuzhiyun {
726*4882a593Smuzhiyun struct sditf_priv *priv = to_sditf_priv(sd);
727*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
728*4882a593Smuzhiyun struct rkcif_vdev_node *node = &cif_dev->stream[0].vnode;
729*4882a593Smuzhiyun int ret = 0;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun if (!on && atomic_dec_return(&priv->power_cnt))
732*4882a593Smuzhiyun return 0;
733*4882a593Smuzhiyun
734*4882a593Smuzhiyun if (on && atomic_inc_return(&priv->power_cnt) > 1)
735*4882a593Smuzhiyun return 0;
736*4882a593Smuzhiyun
737*4882a593Smuzhiyun if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
738*4882a593Smuzhiyun v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
739*4882a593Smuzhiyun "%s, toisp mode %d, hdr %d, set power %d\n",
740*4882a593Smuzhiyun __func__, priv->toisp_inf.link_mode, priv->hdr_cfg.hdr_mode, on);
741*4882a593Smuzhiyun mutex_lock(&cif_dev->stream_lock);
742*4882a593Smuzhiyun if (on) {
743*4882a593Smuzhiyun ret = pm_runtime_resume_and_get(cif_dev->dev);
744*4882a593Smuzhiyun ret |= v4l2_pipeline_pm_get(&node->vdev.entity);
745*4882a593Smuzhiyun } else {
746*4882a593Smuzhiyun v4l2_pipeline_pm_put(&node->vdev.entity);
747*4882a593Smuzhiyun pm_runtime_put_sync(cif_dev->dev);
748*4882a593Smuzhiyun }
749*4882a593Smuzhiyun v4l2_info(&node->vdev, "s_power %d, entity use_count %d\n",
750*4882a593Smuzhiyun on, node->vdev.entity.use_count);
751*4882a593Smuzhiyun mutex_unlock(&cif_dev->stream_lock);
752*4882a593Smuzhiyun }
753*4882a593Smuzhiyun return ret;
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun
sditf_s_rx_buffer(struct v4l2_subdev * sd,void * buf,unsigned int * size)756*4882a593Smuzhiyun static int sditf_s_rx_buffer(struct v4l2_subdev *sd,
757*4882a593Smuzhiyun void *buf, unsigned int *size)
758*4882a593Smuzhiyun {
759*4882a593Smuzhiyun struct sditf_priv *priv = to_sditf_priv(sd);
760*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
761*4882a593Smuzhiyun struct rkcif_sensor_info *sensor = &cif_dev->terminal_sensor;
762*4882a593Smuzhiyun struct rkcif_stream *stream = NULL;
763*4882a593Smuzhiyun struct rkisp_rx_buf *dbufs;
764*4882a593Smuzhiyun struct rkcif_rx_buffer *rx_buf = NULL;
765*4882a593Smuzhiyun unsigned long flags, buffree_flags;
766*4882a593Smuzhiyun u32 diff_time = 1000000;
767*4882a593Smuzhiyun u32 early_time = 0;
768*4882a593Smuzhiyun bool is_free = false;
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun if (!buf) {
771*4882a593Smuzhiyun v4l2_err(&cif_dev->v4l2_dev, "buf is NULL\n");
772*4882a593Smuzhiyun return -EINVAL;
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun dbufs = buf;
776*4882a593Smuzhiyun if (cif_dev->hdr.hdr_mode == NO_HDR) {
777*4882a593Smuzhiyun if (dbufs->type == BUF_SHORT)
778*4882a593Smuzhiyun stream = &cif_dev->stream[0];
779*4882a593Smuzhiyun else
780*4882a593Smuzhiyun return -EINVAL;
781*4882a593Smuzhiyun } else if (cif_dev->hdr.hdr_mode == HDR_X2) {
782*4882a593Smuzhiyun if (dbufs->type == BUF_SHORT)
783*4882a593Smuzhiyun stream = &cif_dev->stream[1];
784*4882a593Smuzhiyun else if (dbufs->type == BUF_MIDDLE)
785*4882a593Smuzhiyun stream = &cif_dev->stream[0];
786*4882a593Smuzhiyun else
787*4882a593Smuzhiyun return -EINVAL;
788*4882a593Smuzhiyun } else if (cif_dev->hdr.hdr_mode == HDR_X3) {
789*4882a593Smuzhiyun if (dbufs->type == BUF_SHORT)
790*4882a593Smuzhiyun stream = &cif_dev->stream[2];
791*4882a593Smuzhiyun else if (dbufs->type == BUF_MIDDLE)
792*4882a593Smuzhiyun stream = &cif_dev->stream[1];
793*4882a593Smuzhiyun else if (dbufs->type == BUF_LONG)
794*4882a593Smuzhiyun stream = &cif_dev->stream[0];
795*4882a593Smuzhiyun else
796*4882a593Smuzhiyun return -EINVAL;
797*4882a593Smuzhiyun }
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun if (!stream)
800*4882a593Smuzhiyun return -EINVAL;
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun rx_buf = to_cif_rx_buf(dbufs);
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun spin_lock_irqsave(&stream->vbq_lock, flags);
805*4882a593Smuzhiyun stream->last_rx_buf_idx = dbufs->sequence + 1;
806*4882a593Smuzhiyun atomic_inc(&stream->buf_cnt);
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun if (!list_empty(&stream->rx_buf_head) &&
809*4882a593Smuzhiyun cif_dev->is_thunderboot &&
810*4882a593Smuzhiyun (dbufs->type == BUF_SHORT ||
811*4882a593Smuzhiyun (dbufs->type != BUF_SHORT && (!dbufs->is_switch)))) {
812*4882a593Smuzhiyun spin_lock_irqsave(&cif_dev->buffree_lock, buffree_flags);
813*4882a593Smuzhiyun list_add_tail(&rx_buf->list_free, &priv->buf_free_list);
814*4882a593Smuzhiyun spin_unlock_irqrestore(&cif_dev->buffree_lock, buffree_flags);
815*4882a593Smuzhiyun atomic_dec(&stream->buf_cnt);
816*4882a593Smuzhiyun stream->total_buf_num--;
817*4882a593Smuzhiyun schedule_work(&priv->buffree_work.work);
818*4882a593Smuzhiyun is_free = true;
819*4882a593Smuzhiyun }
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun if (!is_free && (!dbufs->is_switch)) {
822*4882a593Smuzhiyun list_add_tail(&rx_buf->list, &stream->rx_buf_head);
823*4882a593Smuzhiyun rkcif_assign_check_buffer_update_toisp(stream);
824*4882a593Smuzhiyun if (cif_dev->rdbk_debug) {
825*4882a593Smuzhiyun u32 offset = 0;
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun offset = rx_buf->dummy.size - stream->pixm.plane_fmt[0].bytesperline * 3;
828*4882a593Smuzhiyun memset(rx_buf->dummy.vaddr + offset,
829*4882a593Smuzhiyun 0x00, stream->pixm.plane_fmt[0].bytesperline * 3);
830*4882a593Smuzhiyun if (cif_dev->is_thunderboot)
831*4882a593Smuzhiyun dma_sync_single_for_device(cif_dev->dev,
832*4882a593Smuzhiyun rx_buf->dummy.dma_addr + rx_buf->dummy.size -
833*4882a593Smuzhiyun stream->pixm.plane_fmt[0].bytesperline * 3,
834*4882a593Smuzhiyun stream->pixm.plane_fmt[0].bytesperline * 3,
835*4882a593Smuzhiyun DMA_FROM_DEVICE);
836*4882a593Smuzhiyun else
837*4882a593Smuzhiyun cif_dev->hw_dev->mem_ops->prepare(rx_buf->dummy.mem_priv);
838*4882a593Smuzhiyun }
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun if (dbufs->is_switch && dbufs->type == BUF_SHORT) {
842*4882a593Smuzhiyun if (stream->is_in_vblank)
843*4882a593Smuzhiyun sditf_change_to_online(priv);
844*4882a593Smuzhiyun else
845*4882a593Smuzhiyun stream->is_change_toisp = true;
846*4882a593Smuzhiyun v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev,
847*4882a593Smuzhiyun "switch to online mode\n");
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun spin_unlock_irqrestore(&stream->vbq_lock, flags);
850*4882a593Smuzhiyun
851*4882a593Smuzhiyun if (dbufs->runtime_us && cif_dev->early_line == 0) {
852*4882a593Smuzhiyun if (!cif_dev->sensor_linetime)
853*4882a593Smuzhiyun cif_dev->sensor_linetime = rkcif_get_linetime(stream);
854*4882a593Smuzhiyun cif_dev->isp_runtime_max = dbufs->runtime_us;
855*4882a593Smuzhiyun if (cif_dev->is_thunderboot)
856*4882a593Smuzhiyun diff_time = 200000;
857*4882a593Smuzhiyun else
858*4882a593Smuzhiyun diff_time = 1000000;
859*4882a593Smuzhiyun if (dbufs->runtime_us * 1000 + cif_dev->sensor_linetime > diff_time)
860*4882a593Smuzhiyun early_time = dbufs->runtime_us * 1000 - diff_time;
861*4882a593Smuzhiyun else
862*4882a593Smuzhiyun early_time = diff_time;
863*4882a593Smuzhiyun cif_dev->early_line = div_u64(early_time, cif_dev->sensor_linetime);
864*4882a593Smuzhiyun cif_dev->wait_line_cache = sensor->raw_rect.height - cif_dev->early_line;
865*4882a593Smuzhiyun if (cif_dev->rdbk_debug &&
866*4882a593Smuzhiyun dbufs->sequence < 15)
867*4882a593Smuzhiyun v4l2_info(&cif_dev->v4l2_dev,
868*4882a593Smuzhiyun "%s, isp runtime %d, line time %d, early_line %d, line_intr_cnt %d, seq %d, type %d, dma_addr %x\n",
869*4882a593Smuzhiyun __func__, dbufs->runtime_us, cif_dev->sensor_linetime,
870*4882a593Smuzhiyun cif_dev->early_line, cif_dev->wait_line_cache,
871*4882a593Smuzhiyun dbufs->sequence, dbufs->type, (u32)rx_buf->dummy.dma_addr);
872*4882a593Smuzhiyun } else {
873*4882a593Smuzhiyun if (dbufs->runtime_us < cif_dev->isp_runtime_max) {
874*4882a593Smuzhiyun cif_dev->isp_runtime_max = dbufs->runtime_us;
875*4882a593Smuzhiyun if (cif_dev->is_thunderboot)
876*4882a593Smuzhiyun diff_time = 200000;
877*4882a593Smuzhiyun else
878*4882a593Smuzhiyun diff_time = 1000000;
879*4882a593Smuzhiyun if (dbufs->runtime_us * 1000 + cif_dev->sensor_linetime > diff_time)
880*4882a593Smuzhiyun early_time = dbufs->runtime_us * 1000 - diff_time;
881*4882a593Smuzhiyun else
882*4882a593Smuzhiyun early_time = diff_time;
883*4882a593Smuzhiyun cif_dev->early_line = div_u64(early_time, cif_dev->sensor_linetime);
884*4882a593Smuzhiyun cif_dev->wait_line_cache = sensor->raw_rect.height - cif_dev->early_line;
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun if (cif_dev->rdbk_debug &&
887*4882a593Smuzhiyun dbufs->sequence < 15)
888*4882a593Smuzhiyun v4l2_info(&cif_dev->v4l2_dev,
889*4882a593Smuzhiyun "isp runtime %d, seq %d, type %d, early_line %d, dma addr %x\n",
890*4882a593Smuzhiyun dbufs->runtime_us, dbufs->sequence, dbufs->type,
891*4882a593Smuzhiyun cif_dev->early_line, (u32)rx_buf->dummy.dma_addr);
892*4882a593Smuzhiyun }
893*4882a593Smuzhiyun return 0;
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun
896*4882a593Smuzhiyun static const struct v4l2_subdev_pad_ops sditf_subdev_pad_ops = {
897*4882a593Smuzhiyun .set_fmt = sditf_get_set_fmt,
898*4882a593Smuzhiyun .get_fmt = sditf_get_set_fmt,
899*4882a593Smuzhiyun .get_selection = sditf_get_selection,
900*4882a593Smuzhiyun .get_mbus_config = sditf_g_mbus_config,
901*4882a593Smuzhiyun };
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun static const struct v4l2_subdev_video_ops sditf_video_ops = {
904*4882a593Smuzhiyun .g_frame_interval = sditf_g_frame_interval,
905*4882a593Smuzhiyun .s_stream = sditf_s_stream,
906*4882a593Smuzhiyun .s_rx_buffer = sditf_s_rx_buffer,
907*4882a593Smuzhiyun };
908*4882a593Smuzhiyun
909*4882a593Smuzhiyun static const struct v4l2_subdev_core_ops sditf_core_ops = {
910*4882a593Smuzhiyun .ioctl = sditf_ioctl,
911*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
912*4882a593Smuzhiyun .compat_ioctl32 = sditf_compat_ioctl32,
913*4882a593Smuzhiyun #endif
914*4882a593Smuzhiyun .s_power = sditf_s_power,
915*4882a593Smuzhiyun };
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun static const struct v4l2_subdev_ops sditf_subdev_ops = {
918*4882a593Smuzhiyun .core = &sditf_core_ops,
919*4882a593Smuzhiyun .video = &sditf_video_ops,
920*4882a593Smuzhiyun .pad = &sditf_subdev_pad_ops,
921*4882a593Smuzhiyun };
922*4882a593Smuzhiyun
rkcif_sditf_attach_cifdev(struct sditf_priv * sditf)923*4882a593Smuzhiyun static int rkcif_sditf_attach_cifdev(struct sditf_priv *sditf)
924*4882a593Smuzhiyun {
925*4882a593Smuzhiyun struct device_node *np;
926*4882a593Smuzhiyun struct platform_device *pdev;
927*4882a593Smuzhiyun struct rkcif_device *cif_dev;
928*4882a593Smuzhiyun
929*4882a593Smuzhiyun np = of_parse_phandle(sditf->dev->of_node, "rockchip,cif", 0);
930*4882a593Smuzhiyun if (!np || !of_device_is_available(np)) {
931*4882a593Smuzhiyun dev_err(sditf->dev, "failed to get cif dev node\n");
932*4882a593Smuzhiyun return -ENODEV;
933*4882a593Smuzhiyun }
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun pdev = of_find_device_by_node(np);
936*4882a593Smuzhiyun of_node_put(np);
937*4882a593Smuzhiyun if (!pdev) {
938*4882a593Smuzhiyun dev_err(sditf->dev, "failed to get cif dev from node\n");
939*4882a593Smuzhiyun return -ENODEV;
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun
942*4882a593Smuzhiyun cif_dev = platform_get_drvdata(pdev);
943*4882a593Smuzhiyun if (!cif_dev) {
944*4882a593Smuzhiyun dev_err(sditf->dev, "failed attach cif dev\n");
945*4882a593Smuzhiyun return -EINVAL;
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun cif_dev->sditf[cif_dev->sditf_cnt] = sditf;
949*4882a593Smuzhiyun sditf->cif_dev = cif_dev;
950*4882a593Smuzhiyun cif_dev->sditf_cnt++;
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun return 0;
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun struct sensor_async_subdev {
956*4882a593Smuzhiyun struct v4l2_async_subdev asd;
957*4882a593Smuzhiyun struct v4l2_mbus_config mbus;
958*4882a593Smuzhiyun int lanes;
959*4882a593Smuzhiyun };
960*4882a593Smuzhiyun
sditf_fwnode_parse(struct device * dev,struct v4l2_fwnode_endpoint * vep,struct v4l2_async_subdev * asd)961*4882a593Smuzhiyun static int sditf_fwnode_parse(struct device *dev,
962*4882a593Smuzhiyun struct v4l2_fwnode_endpoint *vep,
963*4882a593Smuzhiyun struct v4l2_async_subdev *asd)
964*4882a593Smuzhiyun {
965*4882a593Smuzhiyun struct sensor_async_subdev *s_asd =
966*4882a593Smuzhiyun container_of(asd, struct sensor_async_subdev, asd);
967*4882a593Smuzhiyun struct v4l2_mbus_config *config = &s_asd->mbus;
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun if (vep->base.port != 0) {
970*4882a593Smuzhiyun dev_err(dev, "sditf has only port 0\n");
971*4882a593Smuzhiyun return -EINVAL;
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun
974*4882a593Smuzhiyun if (vep->bus_type == V4L2_MBUS_CSI2_DPHY ||
975*4882a593Smuzhiyun vep->bus_type == V4L2_MBUS_CSI2_CPHY) {
976*4882a593Smuzhiyun config->type = vep->bus_type;
977*4882a593Smuzhiyun config->flags = vep->bus.mipi_csi2.flags;
978*4882a593Smuzhiyun s_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
979*4882a593Smuzhiyun } else if (vep->bus_type == V4L2_MBUS_CCP2) {
980*4882a593Smuzhiyun config->type = vep->bus_type;
981*4882a593Smuzhiyun s_asd->lanes = vep->bus.mipi_csi1.data_lane;
982*4882a593Smuzhiyun } else {
983*4882a593Smuzhiyun dev_err(dev, "type is not supported\n");
984*4882a593Smuzhiyun return -EINVAL;
985*4882a593Smuzhiyun }
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun switch (s_asd->lanes) {
988*4882a593Smuzhiyun case 1:
989*4882a593Smuzhiyun config->flags |= V4L2_MBUS_CSI2_1_LANE;
990*4882a593Smuzhiyun break;
991*4882a593Smuzhiyun case 2:
992*4882a593Smuzhiyun config->flags |= V4L2_MBUS_CSI2_2_LANE;
993*4882a593Smuzhiyun break;
994*4882a593Smuzhiyun case 3:
995*4882a593Smuzhiyun config->flags |= V4L2_MBUS_CSI2_3_LANE;
996*4882a593Smuzhiyun break;
997*4882a593Smuzhiyun case 4:
998*4882a593Smuzhiyun config->flags |= V4L2_MBUS_CSI2_4_LANE;
999*4882a593Smuzhiyun break;
1000*4882a593Smuzhiyun default:
1001*4882a593Smuzhiyun return -EINVAL;
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun return 0;
1005*4882a593Smuzhiyun }
1006*4882a593Smuzhiyun
rkcif_sditf_get_ctrl(struct v4l2_ctrl * ctrl)1007*4882a593Smuzhiyun static int rkcif_sditf_get_ctrl(struct v4l2_ctrl *ctrl)
1008*4882a593Smuzhiyun {
1009*4882a593Smuzhiyun struct sditf_priv *priv = container_of(ctrl->handler,
1010*4882a593Smuzhiyun struct sditf_priv,
1011*4882a593Smuzhiyun ctrl_handler);
1012*4882a593Smuzhiyun struct v4l2_ctrl *sensor_ctrl = NULL;
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun switch (ctrl->id) {
1015*4882a593Smuzhiyun case V4L2_CID_PIXEL_RATE:
1016*4882a593Smuzhiyun if (priv->cif_dev->terminal_sensor.sd) {
1017*4882a593Smuzhiyun sensor_ctrl = v4l2_ctrl_find(priv->cif_dev->terminal_sensor.sd->ctrl_handler, V4L2_CID_PIXEL_RATE);
1018*4882a593Smuzhiyun if (sensor_ctrl) {
1019*4882a593Smuzhiyun ctrl->val = v4l2_ctrl_g_ctrl_int64(sensor_ctrl);
1020*4882a593Smuzhiyun __v4l2_ctrl_s_ctrl_int64(priv->pixel_rate, ctrl->val);
1021*4882a593Smuzhiyun v4l2_dbg(1, rkcif_debug, &priv->cif_dev->v4l2_dev,
1022*4882a593Smuzhiyun "%s, %s pixel rate %d\n",
1023*4882a593Smuzhiyun __func__, priv->cif_dev->terminal_sensor.sd->name, ctrl->val);
1024*4882a593Smuzhiyun return 0;
1025*4882a593Smuzhiyun } else {
1026*4882a593Smuzhiyun return -EINVAL;
1027*4882a593Smuzhiyun }
1028*4882a593Smuzhiyun }
1029*4882a593Smuzhiyun return -EINVAL;
1030*4882a593Smuzhiyun default:
1031*4882a593Smuzhiyun return -EINVAL;
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun }
1034*4882a593Smuzhiyun
1035*4882a593Smuzhiyun static const struct v4l2_ctrl_ops rkcif_sditf_ctrl_ops = {
1036*4882a593Smuzhiyun .g_volatile_ctrl = rkcif_sditf_get_ctrl,
1037*4882a593Smuzhiyun };
1038*4882a593Smuzhiyun
sditf_notifier_bound(struct v4l2_async_notifier * notifier,struct v4l2_subdev * subdev,struct v4l2_async_subdev * asd)1039*4882a593Smuzhiyun static int sditf_notifier_bound(struct v4l2_async_notifier *notifier,
1040*4882a593Smuzhiyun struct v4l2_subdev *subdev,
1041*4882a593Smuzhiyun struct v4l2_async_subdev *asd)
1042*4882a593Smuzhiyun {
1043*4882a593Smuzhiyun struct sditf_priv *sditf = container_of(notifier,
1044*4882a593Smuzhiyun struct sditf_priv, notifier);
1045*4882a593Smuzhiyun struct media_entity *source_entity, *sink_entity;
1046*4882a593Smuzhiyun int ret = 0;
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun sditf->sensor_sd = subdev;
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun if (sditf->num_sensors == 1) {
1051*4882a593Smuzhiyun v4l2_err(subdev,
1052*4882a593Smuzhiyun "%s: the num of subdev is beyond %d\n",
1053*4882a593Smuzhiyun __func__, sditf->num_sensors);
1054*4882a593Smuzhiyun return -EBUSY;
1055*4882a593Smuzhiyun }
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun if (sditf->sd.entity.pads[0].flags & MEDIA_PAD_FL_SINK) {
1058*4882a593Smuzhiyun source_entity = &subdev->entity;
1059*4882a593Smuzhiyun sink_entity = &sditf->sd.entity;
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun ret = media_create_pad_link(source_entity,
1062*4882a593Smuzhiyun 0,
1063*4882a593Smuzhiyun sink_entity,
1064*4882a593Smuzhiyun 0,
1065*4882a593Smuzhiyun MEDIA_LNK_FL_ENABLED);
1066*4882a593Smuzhiyun if (ret)
1067*4882a593Smuzhiyun v4l2_err(&sditf->sd, "failed to create link for %s\n",
1068*4882a593Smuzhiyun sditf->sensor_sd->name);
1069*4882a593Smuzhiyun }
1070*4882a593Smuzhiyun sditf->sensor_sd = subdev;
1071*4882a593Smuzhiyun ++sditf->num_sensors;
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun v4l2_err(subdev, "Async registered subdev\n");
1074*4882a593Smuzhiyun
1075*4882a593Smuzhiyun return 0;
1076*4882a593Smuzhiyun }
1077*4882a593Smuzhiyun
sditf_notifier_unbind(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd,struct v4l2_async_subdev * asd)1078*4882a593Smuzhiyun static void sditf_notifier_unbind(struct v4l2_async_notifier *notifier,
1079*4882a593Smuzhiyun struct v4l2_subdev *sd,
1080*4882a593Smuzhiyun struct v4l2_async_subdev *asd)
1081*4882a593Smuzhiyun {
1082*4882a593Smuzhiyun struct sditf_priv *sditf = container_of(notifier,
1083*4882a593Smuzhiyun struct sditf_priv,
1084*4882a593Smuzhiyun notifier);
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun sditf->sensor_sd = NULL;
1087*4882a593Smuzhiyun }
1088*4882a593Smuzhiyun
1089*4882a593Smuzhiyun static const struct v4l2_async_notifier_operations sditf_notifier_ops = {
1090*4882a593Smuzhiyun .bound = sditf_notifier_bound,
1091*4882a593Smuzhiyun .unbind = sditf_notifier_unbind,
1092*4882a593Smuzhiyun };
1093*4882a593Smuzhiyun
sditf_subdev_notifier(struct sditf_priv * sditf)1094*4882a593Smuzhiyun static int sditf_subdev_notifier(struct sditf_priv *sditf)
1095*4882a593Smuzhiyun {
1096*4882a593Smuzhiyun struct v4l2_async_notifier *ntf = &sditf->notifier;
1097*4882a593Smuzhiyun int ret;
1098*4882a593Smuzhiyun
1099*4882a593Smuzhiyun v4l2_async_notifier_init(ntf);
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
1102*4882a593Smuzhiyun sditf->dev, &sditf->notifier,
1103*4882a593Smuzhiyun sizeof(struct sensor_async_subdev), 0,
1104*4882a593Smuzhiyun sditf_fwnode_parse);
1105*4882a593Smuzhiyun if (ret < 0)
1106*4882a593Smuzhiyun return ret;
1107*4882a593Smuzhiyun
1108*4882a593Smuzhiyun sditf->sd.subdev_notifier = &sditf->notifier;
1109*4882a593Smuzhiyun sditf->notifier.ops = &sditf_notifier_ops;
1110*4882a593Smuzhiyun
1111*4882a593Smuzhiyun ret = v4l2_async_subdev_notifier_register(&sditf->sd, &sditf->notifier);
1112*4882a593Smuzhiyun if (ret) {
1113*4882a593Smuzhiyun v4l2_err(&sditf->sd,
1114*4882a593Smuzhiyun "failed to register async notifier : %d\n",
1115*4882a593Smuzhiyun ret);
1116*4882a593Smuzhiyun v4l2_async_notifier_cleanup(&sditf->notifier);
1117*4882a593Smuzhiyun return ret;
1118*4882a593Smuzhiyun }
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun return v4l2_async_register_subdev(&sditf->sd);
1121*4882a593Smuzhiyun }
1122*4882a593Smuzhiyun
rkcif_subdev_media_init(struct sditf_priv * priv)1123*4882a593Smuzhiyun static int rkcif_subdev_media_init(struct sditf_priv *priv)
1124*4882a593Smuzhiyun {
1125*4882a593Smuzhiyun struct rkcif_device *cif_dev = priv->cif_dev;
1126*4882a593Smuzhiyun struct v4l2_ctrl_handler *handler = &priv->ctrl_handler;
1127*4882a593Smuzhiyun unsigned long flags = V4L2_CTRL_FLAG_VOLATILE;
1128*4882a593Smuzhiyun int ret;
1129*4882a593Smuzhiyun int pad_num = 0;
1130*4882a593Smuzhiyun
1131*4882a593Smuzhiyun if (priv->is_combine_mode) {
1132*4882a593Smuzhiyun priv->pads[0].flags = MEDIA_PAD_FL_SINK;
1133*4882a593Smuzhiyun priv->pads[1].flags = MEDIA_PAD_FL_SOURCE;
1134*4882a593Smuzhiyun pad_num = 2;
1135*4882a593Smuzhiyun } else {
1136*4882a593Smuzhiyun priv->pads[0].flags = MEDIA_PAD_FL_SOURCE;
1137*4882a593Smuzhiyun pad_num = 1;
1138*4882a593Smuzhiyun }
1139*4882a593Smuzhiyun priv->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_COMPOSER;
1140*4882a593Smuzhiyun ret = media_entity_pads_init(&priv->sd.entity, pad_num, priv->pads);
1141*4882a593Smuzhiyun if (ret < 0)
1142*4882a593Smuzhiyun return ret;
1143*4882a593Smuzhiyun
1144*4882a593Smuzhiyun ret = v4l2_ctrl_handler_init(handler, 1);
1145*4882a593Smuzhiyun if (ret)
1146*4882a593Smuzhiyun return ret;
1147*4882a593Smuzhiyun priv->pixel_rate = v4l2_ctrl_new_std(handler, &rkcif_sditf_ctrl_ops,
1148*4882a593Smuzhiyun V4L2_CID_PIXEL_RATE,
1149*4882a593Smuzhiyun 0, SDITF_PIXEL_RATE_MAX,
1150*4882a593Smuzhiyun 1, SDITF_PIXEL_RATE_MAX);
1151*4882a593Smuzhiyun if (priv->pixel_rate)
1152*4882a593Smuzhiyun priv->pixel_rate->flags |= flags;
1153*4882a593Smuzhiyun priv->sd.ctrl_handler = handler;
1154*4882a593Smuzhiyun if (handler->error) {
1155*4882a593Smuzhiyun v4l2_ctrl_handler_free(handler);
1156*4882a593Smuzhiyun return handler->error;
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun
1159*4882a593Smuzhiyun strncpy(priv->sd.name, dev_name(cif_dev->dev), sizeof(priv->sd.name));
1160*4882a593Smuzhiyun priv->cap_info.width = 0;
1161*4882a593Smuzhiyun priv->cap_info.height = 0;
1162*4882a593Smuzhiyun priv->mode.rdbk_mode = RKISP_VICAP_RDBK_AIQ;
1163*4882a593Smuzhiyun priv->toisp_inf.link_mode = TOISP_NONE;
1164*4882a593Smuzhiyun priv->toisp_inf.ch_info[0].is_valid = false;
1165*4882a593Smuzhiyun priv->toisp_inf.ch_info[1].is_valid = false;
1166*4882a593Smuzhiyun priv->toisp_inf.ch_info[2].is_valid = false;
1167*4882a593Smuzhiyun if (priv->is_combine_mode)
1168*4882a593Smuzhiyun sditf_subdev_notifier(priv);
1169*4882a593Smuzhiyun atomic_set(&priv->power_cnt, 0);
1170*4882a593Smuzhiyun atomic_set(&priv->stream_cnt, 0);
1171*4882a593Smuzhiyun INIT_WORK(&priv->buffree_work.work, sditf_buffree_work);
1172*4882a593Smuzhiyun INIT_LIST_HEAD(&priv->buf_free_list);
1173*4882a593Smuzhiyun return 0;
1174*4882a593Smuzhiyun }
1175*4882a593Smuzhiyun
rkcif_subdev_probe(struct platform_device * pdev)1176*4882a593Smuzhiyun static int rkcif_subdev_probe(struct platform_device *pdev)
1177*4882a593Smuzhiyun {
1178*4882a593Smuzhiyun struct device *dev = &pdev->dev;
1179*4882a593Smuzhiyun struct v4l2_subdev *sd;
1180*4882a593Smuzhiyun struct sditf_priv *priv;
1181*4882a593Smuzhiyun struct device_node *node = dev->of_node;
1182*4882a593Smuzhiyun int ret;
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1185*4882a593Smuzhiyun if (!priv)
1186*4882a593Smuzhiyun return -ENOMEM;
1187*4882a593Smuzhiyun priv->dev = dev;
1188*4882a593Smuzhiyun
1189*4882a593Smuzhiyun sd = &priv->sd;
1190*4882a593Smuzhiyun v4l2_subdev_init(sd, &sditf_subdev_ops);
1191*4882a593Smuzhiyun sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
1192*4882a593Smuzhiyun snprintf(sd->name, sizeof(sd->name), "rockchip-cif-sditf");
1193*4882a593Smuzhiyun sd->dev = dev;
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun platform_set_drvdata(pdev, &sd->entity);
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun ret = rkcif_sditf_attach_cifdev(priv);
1198*4882a593Smuzhiyun if (ret < 0)
1199*4882a593Smuzhiyun return ret;
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun ret = of_property_read_u32(node,
1202*4882a593Smuzhiyun "rockchip,combine-index",
1203*4882a593Smuzhiyun &priv->combine_index);
1204*4882a593Smuzhiyun if (ret) {
1205*4882a593Smuzhiyun priv->is_combine_mode = false;
1206*4882a593Smuzhiyun priv->combine_index = 0;
1207*4882a593Smuzhiyun } else {
1208*4882a593Smuzhiyun priv->is_combine_mode = true;
1209*4882a593Smuzhiyun }
1210*4882a593Smuzhiyun ret = rkcif_subdev_media_init(priv);
1211*4882a593Smuzhiyun if (ret < 0)
1212*4882a593Smuzhiyun return ret;
1213*4882a593Smuzhiyun
1214*4882a593Smuzhiyun pm_runtime_enable(&pdev->dev);
1215*4882a593Smuzhiyun return 0;
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun
rkcif_subdev_remove(struct platform_device * pdev)1218*4882a593Smuzhiyun static int rkcif_subdev_remove(struct platform_device *pdev)
1219*4882a593Smuzhiyun {
1220*4882a593Smuzhiyun struct media_entity *me = platform_get_drvdata(pdev);
1221*4882a593Smuzhiyun struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(me);
1222*4882a593Smuzhiyun
1223*4882a593Smuzhiyun media_entity_cleanup(&sd->entity);
1224*4882a593Smuzhiyun
1225*4882a593Smuzhiyun pm_runtime_disable(&pdev->dev);
1226*4882a593Smuzhiyun return 0;
1227*4882a593Smuzhiyun }
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun static const struct of_device_id rkcif_subdev_match_id[] = {
1230*4882a593Smuzhiyun {
1231*4882a593Smuzhiyun .compatible = "rockchip,rkcif-sditf",
1232*4882a593Smuzhiyun },
1233*4882a593Smuzhiyun {}
1234*4882a593Smuzhiyun };
1235*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, rkcif_subdev_match_id);
1236*4882a593Smuzhiyun
1237*4882a593Smuzhiyun struct platform_driver rkcif_subdev_driver = {
1238*4882a593Smuzhiyun .probe = rkcif_subdev_probe,
1239*4882a593Smuzhiyun .remove = rkcif_subdev_remove,
1240*4882a593Smuzhiyun .driver = {
1241*4882a593Smuzhiyun .name = "rkcif_sditf",
1242*4882a593Smuzhiyun .of_match_table = rkcif_subdev_match_id,
1243*4882a593Smuzhiyun },
1244*4882a593Smuzhiyun };
1245*4882a593Smuzhiyun EXPORT_SYMBOL(rkcif_subdev_driver);
1246*4882a593Smuzhiyun
1247*4882a593Smuzhiyun MODULE_AUTHOR("Rockchip Camera/ISP team");
1248*4882a593Smuzhiyun MODULE_DESCRIPTION("Rockchip CIF platform driver");
1249*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1250