• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * camss-csid.c
4  *
5  * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module
6  *
7  * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
8  * Copyright (C) 2015-2018 Linaro Ltd.
9  */
10 #include <linux/clk.h>
11 #include <linux/completion.h>
12 #include <linux/interrupt.h>
13 #include <linux/io.h>
14 #include <linux/kernel.h>
15 #include <linux/of.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/regulator/consumer.h>
19 #include <media/media-entity.h>
20 #include <media/v4l2-device.h>
21 #include <media/v4l2-event.h>
22 #include <media/v4l2-subdev.h>
23 
24 #include "camss-csid.h"
25 #include "camss-csid-gen1.h"
26 #include "camss.h"
27 
28 #define MSM_CSID_NAME "msm_csid"
29 
30 const char * const csid_testgen_modes[] = {
31 	"Disabled",
32 	"Incrementing",
33 	"Alternating 0x55/0xAA",
34 	"All Zeros 0x00",
35 	"All Ones 0xFF",
36 	"Pseudo-random Data",
37 	"User Specified",
38 	"Complex pattern",
39 	"Color box",
40 	"Color bars",
41 	NULL
42 };
43 
csid_find_code(u32 * codes,unsigned int ncodes,unsigned int match_format_idx,u32 match_code)44 u32 csid_find_code(u32 *codes, unsigned int ncodes,
45 		   unsigned int match_format_idx, u32 match_code)
46 {
47 	int i;
48 
49 	if (!match_code && (match_format_idx >= ncodes))
50 		return 0;
51 
52 	for (i = 0; i < ncodes; i++)
53 		if (match_code) {
54 			if (codes[i] == match_code)
55 				return match_code;
56 		} else {
57 			if (i == match_format_idx)
58 				return codes[i];
59 		}
60 
61 	return codes[0];
62 }
63 
csid_get_fmt_entry(const struct csid_format * formats,unsigned int nformats,u32 code)64 const struct csid_format *csid_get_fmt_entry(const struct csid_format *formats,
65 					     unsigned int nformats,
66 					     u32 code)
67 {
68 	unsigned int i;
69 
70 	for (i = 0; i < nformats; i++)
71 		if (code == formats[i].code)
72 			return &formats[i];
73 
74 	WARN(1, "Unknown format\n");
75 
76 	return &formats[0];
77 }
78 
79 /*
80  * csid_set_clock_rates - Calculate and set clock rates on CSID module
81  * @csiphy: CSID device
82  */
csid_set_clock_rates(struct csid_device * csid)83 static int csid_set_clock_rates(struct csid_device *csid)
84 {
85 	struct device *dev = csid->camss->dev;
86 	const struct csid_format *fmt;
87 	s64 link_freq;
88 	int i, j;
89 	int ret;
90 
91 	fmt = csid_get_fmt_entry(csid->formats, csid->nformats,
92 				 csid->fmt[MSM_CSIPHY_PAD_SINK].code);
93 	link_freq = camss_get_link_freq(&csid->subdev.entity, fmt->bpp,
94 					csid->phy.lane_cnt);
95 	if (link_freq < 0)
96 		link_freq = 0;
97 
98 	for (i = 0; i < csid->nclocks; i++) {
99 		struct camss_clock *clock = &csid->clock[i];
100 
101 		if (!strcmp(clock->name, "csi0") ||
102 		    !strcmp(clock->name, "csi1") ||
103 		    !strcmp(clock->name, "csi2") ||
104 		    !strcmp(clock->name, "csi3")) {
105 			u64 min_rate = link_freq / 4;
106 			long rate;
107 
108 			camss_add_clock_margin(&min_rate);
109 
110 			for (j = 0; j < clock->nfreqs; j++)
111 				if (min_rate < clock->freq[j])
112 					break;
113 
114 			if (j == clock->nfreqs) {
115 				dev_err(dev,
116 					"Pixel clock is too high for CSID\n");
117 				return -EINVAL;
118 			}
119 
120 			/* if sensor pixel clock is not available */
121 			/* set highest possible CSID clock rate */
122 			if (min_rate == 0)
123 				j = clock->nfreqs - 1;
124 
125 			rate = clk_round_rate(clock->clk, clock->freq[j]);
126 			if (rate < 0) {
127 				dev_err(dev, "clk round rate failed: %ld\n",
128 					rate);
129 				return -EINVAL;
130 			}
131 
132 			ret = clk_set_rate(clock->clk, rate);
133 			if (ret < 0) {
134 				dev_err(dev, "clk set rate failed: %d\n", ret);
135 				return ret;
136 			}
137 		} else if (clock->nfreqs) {
138 			clk_set_rate(clock->clk, clock->freq[0]);
139 		}
140 	}
141 
142 	return 0;
143 }
144 
145 /*
146  * csid_set_power - Power on/off CSID module
147  * @sd: CSID V4L2 subdevice
148  * @on: Requested power state
149  *
150  * Return 0 on success or a negative error code otherwise
151  */
csid_set_power(struct v4l2_subdev * sd,int on)152 static int csid_set_power(struct v4l2_subdev *sd, int on)
153 {
154 	struct csid_device *csid = v4l2_get_subdevdata(sd);
155 	struct device *dev = csid->camss->dev;
156 	int ret;
157 
158 	if (on) {
159 		ret = pm_runtime_resume_and_get(dev);
160 		if (ret < 0)
161 			return ret;
162 
163 		ret = regulator_enable(csid->vdda);
164 		if (ret < 0) {
165 			pm_runtime_put_sync(dev);
166 			return ret;
167 		}
168 
169 		ret = csid_set_clock_rates(csid);
170 		if (ret < 0) {
171 			regulator_disable(csid->vdda);
172 			pm_runtime_put_sync(dev);
173 			return ret;
174 		}
175 
176 		ret = camss_enable_clocks(csid->nclocks, csid->clock, dev);
177 		if (ret < 0) {
178 			regulator_disable(csid->vdda);
179 			pm_runtime_put_sync(dev);
180 			return ret;
181 		}
182 
183 		csid->phy.need_vc_update = true;
184 
185 		enable_irq(csid->irq);
186 
187 		ret = csid->ops->reset(csid);
188 		if (ret < 0) {
189 			disable_irq(csid->irq);
190 			camss_disable_clocks(csid->nclocks, csid->clock);
191 			regulator_disable(csid->vdda);
192 			pm_runtime_put_sync(dev);
193 			return ret;
194 		}
195 
196 		csid->ops->hw_version(csid);
197 	} else {
198 		disable_irq(csid->irq);
199 		camss_disable_clocks(csid->nclocks, csid->clock);
200 		ret = regulator_disable(csid->vdda);
201 		pm_runtime_put_sync(dev);
202 	}
203 
204 	return ret;
205 }
206 
207 /*
208  * csid_set_stream - Enable/disable streaming on CSID module
209  * @sd: CSID V4L2 subdevice
210  * @enable: Requested streaming state
211  *
212  * Main configuration of CSID module is also done here.
213  *
214  * Return 0 on success or a negative error code otherwise
215  */
csid_set_stream(struct v4l2_subdev * sd,int enable)216 static int csid_set_stream(struct v4l2_subdev *sd, int enable)
217 {
218 	struct csid_device *csid = v4l2_get_subdevdata(sd);
219 	int ret;
220 
221 	if (enable) {
222 		ret = v4l2_ctrl_handler_setup(&csid->ctrls);
223 		if (ret < 0) {
224 			dev_err(csid->camss->dev,
225 				"could not sync v4l2 controls: %d\n", ret);
226 			return ret;
227 		}
228 
229 		if (!csid->testgen.enabled &&
230 		    !media_entity_remote_pad(&csid->pads[MSM_CSID_PAD_SINK]))
231 			return -ENOLINK;
232 	}
233 
234 	if (csid->phy.need_vc_update) {
235 		csid->ops->configure_stream(csid, enable);
236 		csid->phy.need_vc_update = false;
237 	}
238 
239 	return 0;
240 }
241 
242 /*
243  * __csid_get_format - Get pointer to format structure
244  * @csid: CSID device
245  * @cfg: V4L2 subdev pad configuration
246  * @pad: pad from which format is requested
247  * @which: TRY or ACTIVE format
248  *
249  * Return pointer to TRY or ACTIVE format structure
250  */
251 static struct v4l2_mbus_framefmt *
__csid_get_format(struct csid_device * csid,struct v4l2_subdev_state * sd_state,unsigned int pad,enum v4l2_subdev_format_whence which)252 __csid_get_format(struct csid_device *csid,
253 		  struct v4l2_subdev_state *sd_state,
254 		  unsigned int pad,
255 		  enum v4l2_subdev_format_whence which)
256 {
257 	if (which == V4L2_SUBDEV_FORMAT_TRY)
258 		return v4l2_subdev_get_try_format(&csid->subdev, sd_state,
259 						  pad);
260 
261 	return &csid->fmt[pad];
262 }
263 
264 /*
265  * csid_try_format - Handle try format by pad subdev method
266  * @csid: CSID device
267  * @cfg: V4L2 subdev pad configuration
268  * @pad: pad on which format is requested
269  * @fmt: pointer to v4l2 format structure
270  * @which: wanted subdev format
271  */
csid_try_format(struct csid_device * csid,struct v4l2_subdev_state * sd_state,unsigned int pad,struct v4l2_mbus_framefmt * fmt,enum v4l2_subdev_format_whence which)272 static void csid_try_format(struct csid_device *csid,
273 			    struct v4l2_subdev_state *sd_state,
274 			    unsigned int pad,
275 			    struct v4l2_mbus_framefmt *fmt,
276 			    enum v4l2_subdev_format_whence which)
277 {
278 	unsigned int i;
279 
280 	switch (pad) {
281 	case MSM_CSID_PAD_SINK:
282 		/* Set format on sink pad */
283 
284 		for (i = 0; i < csid->nformats; i++)
285 			if (fmt->code == csid->formats[i].code)
286 				break;
287 
288 		/* If not found, use UYVY as default */
289 		if (i >= csid->nformats)
290 			fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
291 
292 		fmt->width = clamp_t(u32, fmt->width, 1, 8191);
293 		fmt->height = clamp_t(u32, fmt->height, 1, 8191);
294 
295 		fmt->field = V4L2_FIELD_NONE;
296 		fmt->colorspace = V4L2_COLORSPACE_SRGB;
297 
298 		break;
299 
300 	case MSM_CSID_PAD_SRC:
301 		if (csid->testgen_mode->cur.val == 0) {
302 			/* Test generator is disabled, */
303 			/* keep pad formats in sync */
304 			u32 code = fmt->code;
305 
306 			*fmt = *__csid_get_format(csid, sd_state,
307 						      MSM_CSID_PAD_SINK, which);
308 			fmt->code = csid->ops->src_pad_code(csid, fmt->code, 0, code);
309 		} else {
310 			/* Test generator is enabled, set format on source */
311 			/* pad to allow test generator usage */
312 
313 			for (i = 0; i < csid->nformats; i++)
314 				if (csid->formats[i].code == fmt->code)
315 					break;
316 
317 			/* If not found, use UYVY as default */
318 			if (i >= csid->nformats)
319 				fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
320 
321 			fmt->width = clamp_t(u32, fmt->width, 1, 8191);
322 			fmt->height = clamp_t(u32, fmt->height, 1, 8191);
323 
324 			fmt->field = V4L2_FIELD_NONE;
325 		}
326 		break;
327 	}
328 
329 	fmt->colorspace = V4L2_COLORSPACE_SRGB;
330 }
331 
332 /*
333  * csid_enum_mbus_code - Handle pixel format enumeration
334  * @sd: CSID V4L2 subdevice
335  * @cfg: V4L2 subdev pad configuration
336  * @code: pointer to v4l2_subdev_mbus_code_enum structure
337  * return -EINVAL or zero on success
338  */
csid_enum_mbus_code(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_mbus_code_enum * code)339 static int csid_enum_mbus_code(struct v4l2_subdev *sd,
340 			       struct v4l2_subdev_state *sd_state,
341 			       struct v4l2_subdev_mbus_code_enum *code)
342 {
343 	struct csid_device *csid = v4l2_get_subdevdata(sd);
344 
345 	if (code->pad == MSM_CSID_PAD_SINK) {
346 		if (code->index >= csid->nformats)
347 			return -EINVAL;
348 
349 		code->code = csid->formats[code->index].code;
350 	} else {
351 		if (csid->testgen_mode->cur.val == 0) {
352 			struct v4l2_mbus_framefmt *sink_fmt;
353 
354 			sink_fmt = __csid_get_format(csid, sd_state,
355 						     MSM_CSID_PAD_SINK,
356 						     code->which);
357 
358 			code->code = csid->ops->src_pad_code(csid, sink_fmt->code,
359 						       code->index, 0);
360 			if (!code->code)
361 				return -EINVAL;
362 		} else {
363 			if (code->index >= csid->nformats)
364 				return -EINVAL;
365 
366 			code->code = csid->formats[code->index].code;
367 		}
368 	}
369 
370 	return 0;
371 }
372 
373 /*
374  * csid_enum_frame_size - Handle frame size enumeration
375  * @sd: CSID V4L2 subdevice
376  * @cfg: V4L2 subdev pad configuration
377  * @fse: pointer to v4l2_subdev_frame_size_enum structure
378  * return -EINVAL or zero on success
379  */
csid_enum_frame_size(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_frame_size_enum * fse)380 static int csid_enum_frame_size(struct v4l2_subdev *sd,
381 				struct v4l2_subdev_state *sd_state,
382 				struct v4l2_subdev_frame_size_enum *fse)
383 {
384 	struct csid_device *csid = v4l2_get_subdevdata(sd);
385 	struct v4l2_mbus_framefmt format;
386 
387 	if (fse->index != 0)
388 		return -EINVAL;
389 
390 	format.code = fse->code;
391 	format.width = 1;
392 	format.height = 1;
393 	csid_try_format(csid, sd_state, fse->pad, &format, fse->which);
394 	fse->min_width = format.width;
395 	fse->min_height = format.height;
396 
397 	if (format.code != fse->code)
398 		return -EINVAL;
399 
400 	format.code = fse->code;
401 	format.width = -1;
402 	format.height = -1;
403 	csid_try_format(csid, sd_state, fse->pad, &format, fse->which);
404 	fse->max_width = format.width;
405 	fse->max_height = format.height;
406 
407 	return 0;
408 }
409 
410 /*
411  * csid_get_format - Handle get format by pads subdev method
412  * @sd: CSID V4L2 subdevice
413  * @cfg: V4L2 subdev pad configuration
414  * @fmt: pointer to v4l2 subdev format structure
415  *
416  * Return -EINVAL or zero on success
417  */
csid_get_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)418 static int csid_get_format(struct v4l2_subdev *sd,
419 			   struct v4l2_subdev_state *sd_state,
420 			   struct v4l2_subdev_format *fmt)
421 {
422 	struct csid_device *csid = v4l2_get_subdevdata(sd);
423 	struct v4l2_mbus_framefmt *format;
424 
425 	format = __csid_get_format(csid, sd_state, fmt->pad, fmt->which);
426 	if (format == NULL)
427 		return -EINVAL;
428 
429 	fmt->format = *format;
430 
431 	return 0;
432 }
433 
434 /*
435  * csid_set_format - Handle set format by pads subdev method
436  * @sd: CSID V4L2 subdevice
437  * @cfg: V4L2 subdev pad configuration
438  * @fmt: pointer to v4l2 subdev format structure
439  *
440  * Return -EINVAL or zero on success
441  */
csid_set_format(struct v4l2_subdev * sd,struct v4l2_subdev_state * sd_state,struct v4l2_subdev_format * fmt)442 static int csid_set_format(struct v4l2_subdev *sd,
443 			   struct v4l2_subdev_state *sd_state,
444 			   struct v4l2_subdev_format *fmt)
445 {
446 	struct csid_device *csid = v4l2_get_subdevdata(sd);
447 	struct v4l2_mbus_framefmt *format;
448 	int i;
449 
450 	format = __csid_get_format(csid, sd_state, fmt->pad, fmt->which);
451 	if (format == NULL)
452 		return -EINVAL;
453 
454 	csid_try_format(csid, sd_state, fmt->pad, &fmt->format, fmt->which);
455 	*format = fmt->format;
456 
457 	/* Propagate the format from sink to source pads */
458 	if (fmt->pad == MSM_CSID_PAD_SINK) {
459 		for (i = MSM_CSID_PAD_FIRST_SRC; i < MSM_CSID_PADS_NUM; ++i) {
460 			format = __csid_get_format(csid, sd_state, i, fmt->which);
461 
462 			*format = fmt->format;
463 			csid_try_format(csid, sd_state, i, format, fmt->which);
464 		}
465 	}
466 
467 	return 0;
468 }
469 
470 /*
471  * csid_init_formats - Initialize formats on all pads
472  * @sd: CSID V4L2 subdevice
473  * @fh: V4L2 subdev file handle
474  *
475  * Initialize all pad formats with default values.
476  *
477  * Return 0 on success or a negative error code otherwise
478  */
csid_init_formats(struct v4l2_subdev * sd,struct v4l2_subdev_fh * fh)479 static int csid_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
480 {
481 	struct v4l2_subdev_format format = {
482 		.pad = MSM_CSID_PAD_SINK,
483 		.which = fh ? V4L2_SUBDEV_FORMAT_TRY :
484 			      V4L2_SUBDEV_FORMAT_ACTIVE,
485 		.format = {
486 			.code = MEDIA_BUS_FMT_UYVY8_2X8,
487 			.width = 1920,
488 			.height = 1080
489 		}
490 	};
491 
492 	return csid_set_format(sd, fh ? fh->state : NULL, &format);
493 }
494 
495 /*
496  * csid_set_test_pattern - Set test generator's pattern mode
497  * @csid: CSID device
498  * @value: desired test pattern mode
499  *
500  * Return 0 on success or a negative error code otherwise
501  */
csid_set_test_pattern(struct csid_device * csid,s32 value)502 static int csid_set_test_pattern(struct csid_device *csid, s32 value)
503 {
504 	struct csid_testgen_config *tg = &csid->testgen;
505 
506 	/* If CSID is linked to CSIPHY, do not allow to enable test generator */
507 	if (value && media_entity_remote_pad(&csid->pads[MSM_CSID_PAD_SINK]))
508 		return -EBUSY;
509 
510 	tg->enabled = !!value;
511 
512 	return csid->ops->configure_testgen_pattern(csid, value);
513 }
514 
515 /*
516  * csid_s_ctrl - Handle set control subdev method
517  * @ctrl: pointer to v4l2 control structure
518  *
519  * Return 0 on success or a negative error code otherwise
520  */
csid_s_ctrl(struct v4l2_ctrl * ctrl)521 static int csid_s_ctrl(struct v4l2_ctrl *ctrl)
522 {
523 	struct csid_device *csid = container_of(ctrl->handler,
524 						struct csid_device, ctrls);
525 	int ret = -EINVAL;
526 
527 	switch (ctrl->id) {
528 	case V4L2_CID_TEST_PATTERN:
529 		ret = csid_set_test_pattern(csid, ctrl->val);
530 		break;
531 	}
532 
533 	return ret;
534 }
535 
536 static const struct v4l2_ctrl_ops csid_ctrl_ops = {
537 	.s_ctrl = csid_s_ctrl,
538 };
539 
540 /*
541  * msm_csid_subdev_init - Initialize CSID device structure and resources
542  * @csid: CSID device
543  * @res: CSID module resources table
544  * @id: CSID module id
545  *
546  * Return 0 on success or a negative error code otherwise
547  */
msm_csid_subdev_init(struct camss * camss,struct csid_device * csid,const struct resources * res,u8 id)548 int msm_csid_subdev_init(struct camss *camss, struct csid_device *csid,
549 			 const struct resources *res, u8 id)
550 {
551 	struct device *dev = camss->dev;
552 	struct platform_device *pdev = to_platform_device(dev);
553 	struct resource *r;
554 	int i, j;
555 	int ret;
556 
557 	csid->camss = camss;
558 	csid->id = id;
559 
560 	if (camss->version == CAMSS_8x16) {
561 		csid->ops = &csid_ops_4_1;
562 	} else if (camss->version == CAMSS_8x96 ||
563 		   camss->version == CAMSS_660) {
564 		csid->ops = &csid_ops_4_7;
565 	} else if (camss->version == CAMSS_845) {
566 		csid->ops = &csid_ops_170;
567 	} else {
568 		return -EINVAL;
569 	}
570 	csid->ops->subdev_init(csid);
571 
572 	/* Memory */
573 
574 	csid->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]);
575 	if (IS_ERR(csid->base))
576 		return PTR_ERR(csid->base);
577 
578 	/* Interrupt */
579 
580 	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
581 					 res->interrupt[0]);
582 	if (!r) {
583 		dev_err(dev, "missing IRQ\n");
584 		return -EINVAL;
585 	}
586 
587 	csid->irq = r->start;
588 	snprintf(csid->irq_name, sizeof(csid->irq_name), "%s_%s%d",
589 		 dev_name(dev), MSM_CSID_NAME, csid->id);
590 	ret = devm_request_irq(dev, csid->irq, csid->ops->isr,
591 			       IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN,
592 			       csid->irq_name, csid);
593 	if (ret < 0) {
594 		dev_err(dev, "request_irq failed: %d\n", ret);
595 		return ret;
596 	}
597 
598 	/* Clocks */
599 
600 	csid->nclocks = 0;
601 	while (res->clock[csid->nclocks])
602 		csid->nclocks++;
603 
604 	csid->clock = devm_kcalloc(dev, csid->nclocks, sizeof(*csid->clock),
605 				    GFP_KERNEL);
606 	if (!csid->clock)
607 		return -ENOMEM;
608 
609 	for (i = 0; i < csid->nclocks; i++) {
610 		struct camss_clock *clock = &csid->clock[i];
611 
612 		clock->clk = devm_clk_get(dev, res->clock[i]);
613 		if (IS_ERR(clock->clk))
614 			return PTR_ERR(clock->clk);
615 
616 		clock->name = res->clock[i];
617 
618 		clock->nfreqs = 0;
619 		while (res->clock_rate[i][clock->nfreqs])
620 			clock->nfreqs++;
621 
622 		if (!clock->nfreqs) {
623 			clock->freq = NULL;
624 			continue;
625 		}
626 
627 		clock->freq = devm_kcalloc(dev,
628 					   clock->nfreqs,
629 					   sizeof(*clock->freq),
630 					   GFP_KERNEL);
631 		if (!clock->freq)
632 			return -ENOMEM;
633 
634 		for (j = 0; j < clock->nfreqs; j++)
635 			clock->freq[j] = res->clock_rate[i][j];
636 	}
637 
638 	/* Regulator */
639 
640 	csid->vdda = devm_regulator_get(dev, res->regulator[0]);
641 	if (IS_ERR(csid->vdda)) {
642 		dev_err(dev, "could not get regulator\n");
643 		return PTR_ERR(csid->vdda);
644 	}
645 
646 	init_completion(&csid->reset_complete);
647 
648 	return 0;
649 }
650 
651 /*
652  * msm_csid_get_csid_id - Get CSID HW module id
653  * @entity: Pointer to CSID media entity structure
654  * @id: Return CSID HW module id here
655  */
msm_csid_get_csid_id(struct media_entity * entity,u8 * id)656 void msm_csid_get_csid_id(struct media_entity *entity, u8 *id)
657 {
658 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
659 	struct csid_device *csid = v4l2_get_subdevdata(sd);
660 
661 	*id = csid->id;
662 }
663 
664 /*
665  * csid_get_lane_assign - Calculate CSI2 lane assign configuration parameter
666  * @lane_cfg - CSI2 lane configuration
667  *
668  * Return lane assign
669  */
csid_get_lane_assign(struct csiphy_lanes_cfg * lane_cfg)670 static u32 csid_get_lane_assign(struct csiphy_lanes_cfg *lane_cfg)
671 {
672 	u32 lane_assign = 0;
673 	int i;
674 
675 	for (i = 0; i < lane_cfg->num_data; i++)
676 		lane_assign |= lane_cfg->data[i].pos << (i * 4);
677 
678 	return lane_assign;
679 }
680 
681 /*
682  * csid_link_setup - Setup CSID connections
683  * @entity: Pointer to media entity structure
684  * @local: Pointer to local pad
685  * @remote: Pointer to remote pad
686  * @flags: Link flags
687  *
688  * Return 0 on success
689  */
csid_link_setup(struct media_entity * entity,const struct media_pad * local,const struct media_pad * remote,u32 flags)690 static int csid_link_setup(struct media_entity *entity,
691 			   const struct media_pad *local,
692 			   const struct media_pad *remote, u32 flags)
693 {
694 	if (flags & MEDIA_LNK_FL_ENABLED)
695 		if (media_entity_remote_pad(local))
696 			return -EBUSY;
697 
698 	if ((local->flags & MEDIA_PAD_FL_SINK) &&
699 	    (flags & MEDIA_LNK_FL_ENABLED)) {
700 		struct v4l2_subdev *sd;
701 		struct csid_device *csid;
702 		struct csiphy_device *csiphy;
703 		struct csiphy_lanes_cfg *lane_cfg;
704 
705 		sd = media_entity_to_v4l2_subdev(entity);
706 		csid = v4l2_get_subdevdata(sd);
707 
708 		/* If test generator is enabled */
709 		/* do not allow a link from CSIPHY to CSID */
710 		if (csid->testgen_mode->cur.val != 0)
711 			return -EBUSY;
712 
713 		sd = media_entity_to_v4l2_subdev(remote->entity);
714 		csiphy = v4l2_get_subdevdata(sd);
715 
716 		/* If a sensor is not linked to CSIPHY */
717 		/* do no allow a link from CSIPHY to CSID */
718 		if (!csiphy->cfg.csi2)
719 			return -EPERM;
720 
721 		csid->phy.csiphy_id = csiphy->id;
722 
723 		lane_cfg = &csiphy->cfg.csi2->lane_cfg;
724 		csid->phy.lane_cnt = lane_cfg->num_data;
725 		csid->phy.lane_assign = csid_get_lane_assign(lane_cfg);
726 	}
727 	/* Decide which virtual channels to enable based on which source pads are enabled */
728 	if (local->flags & MEDIA_PAD_FL_SOURCE) {
729 		struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
730 		struct csid_device *csid = v4l2_get_subdevdata(sd);
731 		struct device *dev = csid->camss->dev;
732 
733 		if (flags & MEDIA_LNK_FL_ENABLED)
734 			csid->phy.en_vc |= BIT(local->index - 1);
735 		else
736 			csid->phy.en_vc &= ~BIT(local->index - 1);
737 
738 		csid->phy.need_vc_update = true;
739 
740 		dev_dbg(dev, "%s: Enabled CSID virtual channels mask 0x%x\n",
741 			__func__, csid->phy.en_vc);
742 	}
743 
744 	return 0;
745 }
746 
747 static const struct v4l2_subdev_core_ops csid_core_ops = {
748 	.s_power = csid_set_power,
749 	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
750 	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
751 };
752 
753 static const struct v4l2_subdev_video_ops csid_video_ops = {
754 	.s_stream = csid_set_stream,
755 };
756 
757 static const struct v4l2_subdev_pad_ops csid_pad_ops = {
758 	.enum_mbus_code = csid_enum_mbus_code,
759 	.enum_frame_size = csid_enum_frame_size,
760 	.get_fmt = csid_get_format,
761 	.set_fmt = csid_set_format,
762 };
763 
764 static const struct v4l2_subdev_ops csid_v4l2_ops = {
765 	.core = &csid_core_ops,
766 	.video = &csid_video_ops,
767 	.pad = &csid_pad_ops,
768 };
769 
770 static const struct v4l2_subdev_internal_ops csid_v4l2_internal_ops = {
771 	.open = csid_init_formats,
772 };
773 
774 static const struct media_entity_operations csid_media_ops = {
775 	.link_setup = csid_link_setup,
776 	.link_validate = v4l2_subdev_link_validate,
777 };
778 
779 /*
780  * msm_csid_register_entity - Register subdev node for CSID module
781  * @csid: CSID device
782  * @v4l2_dev: V4L2 device
783  *
784  * Return 0 on success or a negative error code otherwise
785  */
msm_csid_register_entity(struct csid_device * csid,struct v4l2_device * v4l2_dev)786 int msm_csid_register_entity(struct csid_device *csid,
787 			     struct v4l2_device *v4l2_dev)
788 {
789 	struct v4l2_subdev *sd = &csid->subdev;
790 	struct media_pad *pads = csid->pads;
791 	struct device *dev = csid->camss->dev;
792 	int i;
793 	int ret;
794 
795 	v4l2_subdev_init(sd, &csid_v4l2_ops);
796 	sd->internal_ops = &csid_v4l2_internal_ops;
797 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
798 		     V4L2_SUBDEV_FL_HAS_EVENTS;
799 	snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d",
800 		 MSM_CSID_NAME, csid->id);
801 	v4l2_set_subdevdata(sd, csid);
802 
803 	ret = v4l2_ctrl_handler_init(&csid->ctrls, 1);
804 	if (ret < 0) {
805 		dev_err(dev, "Failed to init ctrl handler: %d\n", ret);
806 		return ret;
807 	}
808 
809 	csid->testgen_mode = v4l2_ctrl_new_std_menu_items(&csid->ctrls,
810 				&csid_ctrl_ops, V4L2_CID_TEST_PATTERN,
811 				csid->testgen.nmodes, 0, 0,
812 				csid->testgen.modes);
813 
814 	if (csid->ctrls.error) {
815 		dev_err(dev, "Failed to init ctrl: %d\n", csid->ctrls.error);
816 		ret = csid->ctrls.error;
817 		goto free_ctrl;
818 	}
819 
820 	csid->subdev.ctrl_handler = &csid->ctrls;
821 
822 	ret = csid_init_formats(sd, NULL);
823 	if (ret < 0) {
824 		dev_err(dev, "Failed to init format: %d\n", ret);
825 		goto free_ctrl;
826 	}
827 
828 	pads[MSM_CSID_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
829 	for (i = MSM_CSID_PAD_FIRST_SRC; i < MSM_CSID_PADS_NUM; ++i)
830 		pads[i].flags = MEDIA_PAD_FL_SOURCE;
831 
832 	sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
833 	sd->entity.ops = &csid_media_ops;
834 	ret = media_entity_pads_init(&sd->entity, MSM_CSID_PADS_NUM, pads);
835 	if (ret < 0) {
836 		dev_err(dev, "Failed to init media entity: %d\n", ret);
837 		goto free_ctrl;
838 	}
839 
840 	ret = v4l2_device_register_subdev(v4l2_dev, sd);
841 	if (ret < 0) {
842 		dev_err(dev, "Failed to register subdev: %d\n", ret);
843 		goto media_cleanup;
844 	}
845 
846 	return 0;
847 
848 media_cleanup:
849 	media_entity_cleanup(&sd->entity);
850 free_ctrl:
851 	v4l2_ctrl_handler_free(&csid->ctrls);
852 
853 	return ret;
854 }
855 
856 /*
857  * msm_csid_unregister_entity - Unregister CSID module subdev node
858  * @csid: CSID device
859  */
msm_csid_unregister_entity(struct csid_device * csid)860 void msm_csid_unregister_entity(struct csid_device *csid)
861 {
862 	v4l2_device_unregister_subdev(&csid->subdev);
863 	media_entity_cleanup(&csid->subdev.entity);
864 	v4l2_ctrl_handler_free(&csid->ctrls);
865 }
866