• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Rockchip MIPI CSI2 DPHY driver
4  *
5  * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
6  */
7 
8 #include <linux/clk.h>
9 #include <linux/delay.h>
10 #include <linux/io.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/of_graph.h>
14 #include <linux/of_platform.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/regmap.h>
18 #include <linux/mfd/syscon.h>
19 #include <media/media-entity.h>
20 #include <media/v4l2-ctrls.h>
21 #include <media/v4l2-fwnode.h>
22 #include <media/v4l2-subdev.h>
23 #include <media/v4l2-device.h>
24 #include "phy-rockchip-csi2-dphy-common.h"
25 
26 struct sensor_async_subdev {
27 	struct v4l2_async_subdev asd;
28 	struct v4l2_mbus_config mbus;
29 	int lanes;
30 };
31 
32 static LIST_HEAD(csi2dphy_device_list);
33 
to_csi2_dphy(struct v4l2_subdev * subdev)34 static inline struct csi2_dphy *to_csi2_dphy(struct v4l2_subdev *subdev)
35 {
36 	return container_of(subdev, struct csi2_dphy, sd);
37 }
38 
get_remote_sensor(struct v4l2_subdev * sd)39 static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd)
40 {
41 	struct media_pad *local, *remote;
42 	struct media_entity *sensor_me;
43 
44 	local = &sd->entity.pads[CSI2_DPHY_RX_PAD_SINK];
45 	remote = media_entity_remote_pad(local);
46 	if (!remote) {
47 		v4l2_warn(sd, "No link between dphy and sensor\n");
48 		return NULL;
49 	}
50 
51 	sensor_me = media_entity_remote_pad(local)->entity;
52 	return media_entity_to_v4l2_subdev(sensor_me);
53 }
54 
sd_to_sensor(struct csi2_dphy * dphy,struct v4l2_subdev * sd)55 static struct csi2_sensor *sd_to_sensor(struct csi2_dphy *dphy,
56 					   struct v4l2_subdev *sd)
57 {
58 	int i;
59 
60 	for (i = 0; i < dphy->num_sensors; ++i)
61 		if (dphy->sensors[i].sd == sd)
62 			return &dphy->sensors[i];
63 
64 	return NULL;
65 }
66 
csi2_dphy_get_sensor_data_rate(struct v4l2_subdev * sd)67 static int csi2_dphy_get_sensor_data_rate(struct v4l2_subdev *sd)
68 {
69 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
70 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
71 	struct v4l2_ctrl *link_freq;
72 	struct v4l2_querymenu qm = { .id = V4L2_CID_LINK_FREQ, };
73 	int ret;
74 
75 	link_freq = v4l2_ctrl_find(sensor_sd->ctrl_handler, V4L2_CID_LINK_FREQ);
76 	if (!link_freq) {
77 		v4l2_warn(sd, "No pixel rate control in subdev\n");
78 		return -EPIPE;
79 	}
80 
81 	qm.index = v4l2_ctrl_g_ctrl(link_freq);
82 	ret = v4l2_querymenu(sensor_sd->ctrl_handler, &qm);
83 	if (ret < 0) {
84 		v4l2_err(sd, "Failed to get menu item\n");
85 		return ret;
86 	}
87 
88 	if (!qm.value) {
89 		v4l2_err(sd, "Invalid link_freq\n");
90 		return -EINVAL;
91 	}
92 	dphy->data_rate_mbps = qm.value * 2;
93 	do_div(dphy->data_rate_mbps, 1000 * 1000);
94 	v4l2_info(sd, "dphy%d, data_rate_mbps %lld\n",
95 		  dphy->phy_index, dphy->data_rate_mbps);
96 	return 0;
97 }
98 
csi2_dphy_update_sensor_mbus(struct v4l2_subdev * sd)99 static int csi2_dphy_update_sensor_mbus(struct v4l2_subdev *sd)
100 {
101 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
102 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
103 	struct csi2_sensor *sensor = sd_to_sensor(dphy, sensor_sd);
104 	struct v4l2_mbus_config mbus;
105 	int ret;
106 
107 	ret = v4l2_subdev_call(sensor_sd, pad, get_mbus_config, 0, &mbus);
108 	if (ret)
109 		return ret;
110 
111 	sensor->mbus = mbus;
112 	switch (mbus.flags & V4L2_MBUS_CSI2_LANES) {
113 	case V4L2_MBUS_CSI2_1_LANE:
114 		sensor->lanes = 1;
115 		break;
116 	case V4L2_MBUS_CSI2_2_LANE:
117 		sensor->lanes = 2;
118 		break;
119 	case V4L2_MBUS_CSI2_3_LANE:
120 		sensor->lanes = 3;
121 		break;
122 	case V4L2_MBUS_CSI2_4_LANE:
123 		sensor->lanes = 4;
124 		break;
125 	default:
126 		return -EINVAL;
127 	}
128 
129 	return 0;
130 }
131 
csi2_dphy_s_stream_start(struct v4l2_subdev * sd)132 static int csi2_dphy_s_stream_start(struct v4l2_subdev *sd)
133 {
134 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
135 	struct csi2_dphy_hw *hw = dphy->dphy_hw;
136 	int  ret = 0;
137 
138 	if (dphy->is_streaming)
139 		return 0;
140 
141 	ret = csi2_dphy_get_sensor_data_rate(sd);
142 	if (ret < 0)
143 		return ret;
144 
145 	csi2_dphy_update_sensor_mbus(sd);
146 
147 	if (hw->stream_on)
148 		hw->stream_on(dphy, sd);
149 
150 	dphy->is_streaming = true;
151 
152 	return 0;
153 }
154 
csi2_dphy_s_stream_stop(struct v4l2_subdev * sd)155 static int csi2_dphy_s_stream_stop(struct v4l2_subdev *sd)
156 {
157 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
158 	struct csi2_dphy_hw *hw = dphy->dphy_hw;
159 
160 	if (!dphy->is_streaming)
161 		return 0;
162 
163 	if (hw->stream_off)
164 		hw->stream_off(dphy, sd);
165 
166 	dphy->is_streaming = false;
167 
168 	dev_info(dphy->dev, "%s stream stop, dphy%d\n",
169 		 __func__, dphy->phy_index);
170 
171 	return 0;
172 }
173 
csi2_dphy_s_stream(struct v4l2_subdev * sd,int on)174 static int csi2_dphy_s_stream(struct v4l2_subdev *sd, int on)
175 {
176 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
177 	int ret = 0;
178 
179 	mutex_lock(&dphy->mutex);
180 	if (on)
181 		ret = csi2_dphy_s_stream_start(sd);
182 	else
183 		ret = csi2_dphy_s_stream_stop(sd);
184 	mutex_unlock(&dphy->mutex);
185 
186 	dev_info(dphy->dev, "%s stream on:%d, dphy%d\n",
187 		 __func__, on, dphy->phy_index);
188 
189 	return ret;
190 }
191 
csi2_dphy_g_frame_interval(struct v4l2_subdev * sd,struct v4l2_subdev_frame_interval * fi)192 static int csi2_dphy_g_frame_interval(struct v4l2_subdev *sd,
193 					    struct v4l2_subdev_frame_interval *fi)
194 {
195 	struct v4l2_subdev *sensor = get_remote_sensor(sd);
196 
197 	if (sensor)
198 		return v4l2_subdev_call(sensor, video, g_frame_interval, fi);
199 
200 	return -EINVAL;
201 }
202 
csi2_dphy_g_mbus_config(struct v4l2_subdev * sd,unsigned int pad_id,struct v4l2_mbus_config * config)203 static int csi2_dphy_g_mbus_config(struct v4l2_subdev *sd,
204 				   unsigned int pad_id,
205 				   struct v4l2_mbus_config *config)
206 {
207 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
208 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
209 	struct csi2_sensor *sensor;
210 
211 	if (!sensor_sd)
212 		return -ENODEV;
213 	sensor = sd_to_sensor(dphy, sensor_sd);
214 	csi2_dphy_update_sensor_mbus(sd);
215 	*config = sensor->mbus;
216 
217 	return 0;
218 }
219 
csi2_dphy_s_power(struct v4l2_subdev * sd,int on)220 static int csi2_dphy_s_power(struct v4l2_subdev *sd, int on)
221 {
222 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
223 
224 	if (on)
225 		return pm_runtime_get_sync(dphy->dev);
226 	else
227 		return pm_runtime_put(dphy->dev);
228 }
229 
csi2_dphy_runtime_suspend(struct device * dev)230 static __maybe_unused int csi2_dphy_runtime_suspend(struct device *dev)
231 {
232 	struct media_entity *me = dev_get_drvdata(dev);
233 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(me);
234 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
235 	struct csi2_dphy_hw *hw = dphy->dphy_hw;
236 
237 	if (hw)
238 		clk_bulk_disable_unprepare(hw->num_clks, hw->clks_bulk);
239 
240 	return 0;
241 }
242 
csi2_dphy_runtime_resume(struct device * dev)243 static __maybe_unused int csi2_dphy_runtime_resume(struct device *dev)
244 {
245 	struct media_entity *me = dev_get_drvdata(dev);
246 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(me);
247 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
248 	struct csi2_dphy_hw *hw = dphy->dphy_hw;
249 	int ret;
250 
251 	if (hw) {
252 		ret = clk_bulk_prepare_enable(hw->num_clks, hw->clks_bulk);
253 		if (ret) {
254 			dev_err(hw->dev, "failed to enable clks\n");
255 			return ret;
256 		}
257 	}
258 
259 	return 0;
260 }
261 
262 /* dphy accepts all fmt/size from sensor */
csi2_dphy_get_set_fmt(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_format * fmt)263 static int csi2_dphy_get_set_fmt(struct v4l2_subdev *sd,
264 				struct v4l2_subdev_pad_config *cfg,
265 				struct v4l2_subdev_format *fmt)
266 {
267 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
268 	struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
269 	struct csi2_sensor *sensor = sd_to_sensor(dphy, sensor_sd);
270 	int ret;
271 	/*
272 	 * Do not allow format changes and just relay whatever
273 	 * set currently in the sensor.
274 	 */
275 	if (!sensor_sd)
276 		return -ENODEV;
277 	ret = v4l2_subdev_call(sensor_sd, pad, get_fmt, NULL, fmt);
278 	if (!ret && fmt->pad == 0)
279 		sensor->format = fmt->format;
280 	return ret;
281 }
282 
csi2_dphy_get_selection(struct v4l2_subdev * sd,struct v4l2_subdev_pad_config * cfg,struct v4l2_subdev_selection * sel)283 static int csi2_dphy_get_selection(struct v4l2_subdev *sd,
284 				  struct v4l2_subdev_pad_config *cfg,
285 				  struct v4l2_subdev_selection *sel)
286 {
287 	struct v4l2_subdev *sensor = get_remote_sensor(sd);
288 
289 	return v4l2_subdev_call(sensor, pad, get_selection, NULL, sel);
290 }
291 
292 static const struct v4l2_subdev_core_ops csi2_dphy_core_ops = {
293 	.s_power = csi2_dphy_s_power,
294 };
295 
296 static const struct v4l2_subdev_video_ops csi2_dphy_video_ops = {
297 	.g_frame_interval = csi2_dphy_g_frame_interval,
298 	.s_stream = csi2_dphy_s_stream,
299 };
300 
301 static const struct v4l2_subdev_pad_ops csi2_dphy_subdev_pad_ops = {
302 	.set_fmt = csi2_dphy_get_set_fmt,
303 	.get_fmt = csi2_dphy_get_set_fmt,
304 	.get_selection = csi2_dphy_get_selection,
305 	.get_mbus_config = csi2_dphy_g_mbus_config,
306 };
307 
308 static const struct v4l2_subdev_ops csi2_dphy_subdev_ops = {
309 	.core = &csi2_dphy_core_ops,
310 	.video = &csi2_dphy_video_ops,
311 	.pad = &csi2_dphy_subdev_pad_ops,
312 };
313 
314 /* The .bound() notifier callback when a match is found */
315 static int
rockchip_csi2_dphy_notifier_bound(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd,struct v4l2_async_subdev * asd)316 rockchip_csi2_dphy_notifier_bound(struct v4l2_async_notifier *notifier,
317 					   struct v4l2_subdev *sd,
318 					   struct v4l2_async_subdev *asd)
319 {
320 	struct csi2_dphy *dphy = container_of(notifier,
321 					      struct csi2_dphy,
322 					      notifier);
323 	struct sensor_async_subdev *s_asd = container_of(asd,
324 					struct sensor_async_subdev, asd);
325 	struct csi2_sensor *sensor;
326 	unsigned int pad, ret;
327 
328 	if (dphy->num_sensors == ARRAY_SIZE(dphy->sensors))
329 		return -EBUSY;
330 
331 	sensor = &dphy->sensors[dphy->num_sensors++];
332 	sensor->lanes = s_asd->lanes;
333 	sensor->mbus = s_asd->mbus;
334 	sensor->sd = sd;
335 
336 	dev_info(dphy->dev, "dphy%d matches %s:bus type %d\n",
337 		 dphy->phy_index, sd->name, s_asd->mbus.type);
338 
339 	for (pad = 0; pad < sensor->sd->entity.num_pads; pad++)
340 		if (sensor->sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE)
341 			break;
342 
343 	if (pad == sensor->sd->entity.num_pads) {
344 		dev_err(dphy->dev,
345 			"failed to find src pad for %s\n",
346 			sensor->sd->name);
347 
348 		return -ENXIO;
349 	}
350 
351 	ret = media_create_pad_link(
352 			&sensor->sd->entity, pad,
353 			&dphy->sd.entity, CSI2_DPHY_RX_PAD_SINK,
354 			dphy->num_sensors != 1 ? 0 : MEDIA_LNK_FL_ENABLED);
355 	if (ret) {
356 		dev_err(dphy->dev,
357 			"failed to create link for %s\n",
358 			sensor->sd->name);
359 		return ret;
360 	}
361 
362 	return 0;
363 }
364 
365 /* The .unbind callback */
366 static void
rockchip_csi2_dphy_notifier_unbind(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd,struct v4l2_async_subdev * asd)367 rockchip_csi2_dphy_notifier_unbind(struct v4l2_async_notifier *notifier,
368 				  struct v4l2_subdev *sd,
369 				  struct v4l2_async_subdev *asd)
370 {
371 	struct csi2_dphy *dphy = container_of(notifier,
372 						  struct csi2_dphy,
373 						  notifier);
374 	struct csi2_sensor *sensor = sd_to_sensor(dphy, sd);
375 
376 	sensor->sd = NULL;
377 }
378 
379 static const struct
380 v4l2_async_notifier_operations rockchip_csi2_dphy_async_ops = {
381 	.bound = rockchip_csi2_dphy_notifier_bound,
382 	.unbind = rockchip_csi2_dphy_notifier_unbind,
383 };
384 
rockchip_csi2_dphy_fwnode_parse(struct device * dev,struct v4l2_fwnode_endpoint * vep,struct v4l2_async_subdev * asd)385 static int rockchip_csi2_dphy_fwnode_parse(struct device *dev,
386 					  struct v4l2_fwnode_endpoint *vep,
387 					  struct v4l2_async_subdev *asd)
388 {
389 	struct sensor_async_subdev *s_asd =
390 			container_of(asd, struct sensor_async_subdev, asd);
391 	struct v4l2_mbus_config *config = &s_asd->mbus;
392 
393 	if (vep->base.port != 0) {
394 		dev_err(dev, "The PHY has only port 0\n");
395 		return -EINVAL;
396 	}
397 
398 	if (vep->bus_type == V4L2_MBUS_CSI2_DPHY) {
399 		config->type = V4L2_MBUS_CSI2_DPHY;
400 		config->flags = vep->bus.mipi_csi2.flags;
401 		s_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
402 	} else {
403 		dev_err(dev, "Only CSI2 type is currently supported\n");
404 		return -EINVAL;
405 	}
406 
407 	switch (s_asd->lanes) {
408 	case 1:
409 		config->flags |= V4L2_MBUS_CSI2_1_LANE;
410 		break;
411 	case 2:
412 		config->flags |= V4L2_MBUS_CSI2_2_LANE;
413 		break;
414 	case 3:
415 		config->flags |= V4L2_MBUS_CSI2_3_LANE;
416 		break;
417 	case 4:
418 		config->flags |= V4L2_MBUS_CSI2_4_LANE;
419 		break;
420 	default:
421 		return -EINVAL;
422 	}
423 
424 	return 0;
425 }
426 
rockchip_csi2dphy_media_init(struct csi2_dphy * dphy)427 static int rockchip_csi2dphy_media_init(struct csi2_dphy *dphy)
428 {
429 	int ret;
430 
431 	dphy->pads[CSI2_DPHY_RX_PAD_SOURCE].flags =
432 		MEDIA_PAD_FL_SOURCE | MEDIA_PAD_FL_MUST_CONNECT;
433 	dphy->pads[CSI2_DPHY_RX_PAD_SINK].flags =
434 		MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
435 	dphy->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
436 	ret = media_entity_pads_init(&dphy->sd.entity,
437 				CSI2_DPHY_RX_PADS_NUM, dphy->pads);
438 	if (ret < 0)
439 		return ret;
440 
441 	v4l2_async_notifier_init(&dphy->notifier);
442 
443 	ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
444 		dphy->dev, &dphy->notifier,
445 		sizeof(struct sensor_async_subdev), 0,
446 		rockchip_csi2_dphy_fwnode_parse);
447 	if (ret < 0)
448 		return ret;
449 
450 	dphy->sd.subdev_notifier = &dphy->notifier;
451 	dphy->notifier.ops = &rockchip_csi2_dphy_async_ops;
452 	ret = v4l2_async_subdev_notifier_register(&dphy->sd, &dphy->notifier);
453 	if (ret) {
454 		dev_err(dphy->dev,
455 			"failed to register async notifier : %d\n", ret);
456 		v4l2_async_notifier_cleanup(&dphy->notifier);
457 		return ret;
458 	}
459 
460 	return v4l2_async_register_subdev(&dphy->sd);
461 }
462 
rockchip_csi2_dphy_attach_hw(struct csi2_dphy * dphy)463 static int rockchip_csi2_dphy_attach_hw(struct csi2_dphy *dphy)
464 {
465 	struct platform_device *plat_dev;
466 	struct device *dev = dphy->dev;
467 	struct csi2_dphy_hw *dphy_hw;
468 	struct device_node *np;
469 	enum csi2_dphy_lane_mode target_mode;
470 	int i;
471 
472 	if (dphy->phy_index % 3 == 0)
473 		target_mode = LANE_MODE_FULL;
474 	else
475 		target_mode = LANE_MODE_SPLIT;
476 
477 	np = of_parse_phandle(dev->of_node, "rockchip,hw", 0);
478 	if (!np || !of_device_is_available(np)) {
479 		dev_err(dphy->dev,
480 			"failed to get dphy%d hw node\n", dphy->phy_index);
481 		return -ENODEV;
482 	}
483 
484 	plat_dev = of_find_device_by_node(np);
485 	of_node_put(np);
486 	if (!plat_dev) {
487 		dev_err(dphy->dev,
488 			"failed to get dphy%d hw from node\n",
489 			dphy->phy_index);
490 		return -ENODEV;
491 	}
492 
493 	dphy_hw = platform_get_drvdata(plat_dev);
494 	if (!dphy_hw) {
495 		dev_err(dphy->dev,
496 			"failed attach dphy%d hw\n",
497 			dphy->phy_index);
498 		return -EINVAL;
499 	}
500 
501 	if (dphy_hw->lane_mode == LANE_MODE_UNDEF) {
502 		dphy_hw->lane_mode = target_mode;
503 	} else {
504 		struct csi2_dphy *phy = dphy_hw->dphy_dev[0];
505 
506 		for (i = 0; i < dphy_hw->dphy_dev_num; i++) {
507 			if (dphy_hw->dphy_dev[i]->lane_mode == dphy_hw->lane_mode) {
508 				phy = dphy_hw->dphy_dev[i];
509 				break;
510 			}
511 		}
512 
513 		if (target_mode != dphy_hw->lane_mode) {
514 			dev_err(dphy->dev,
515 				"Err:csi2 dphy hw has been set as %s mode by phy%d, target mode is:%s\n",
516 				dphy_hw->lane_mode == LANE_MODE_FULL ? "full" : "split",
517 				phy->phy_index,
518 				target_mode == LANE_MODE_FULL ? "full" : "split");
519 			return -ENODEV;
520 		}
521 	}
522 
523 	dphy_hw->dphy_dev[dphy_hw->dphy_dev_num] = dphy;
524 	dphy_hw->dphy_dev_num++;
525 	dphy->dphy_hw = dphy_hw;
526 
527 	return 0;
528 }
529 
rockchip_csi2_dphy_detach_hw(struct csi2_dphy * dphy)530 static int rockchip_csi2_dphy_detach_hw(struct csi2_dphy *dphy)
531 {
532 	struct csi2_dphy_hw *dphy_hw = dphy->dphy_hw;
533 	struct csi2_dphy *csi2_dphy = NULL;
534 	int i;
535 
536 	for (i = 0; i < dphy_hw->dphy_dev_num; i++) {
537 		csi2_dphy = dphy_hw->dphy_dev[i];
538 		if (csi2_dphy &&
539 		    csi2_dphy->phy_index == dphy->phy_index) {
540 			dphy_hw->dphy_dev[i] = NULL;
541 			dphy_hw->dphy_dev_num--;
542 			break;
543 		}
544 	}
545 
546 	return 0;
547 }
548 
549 static struct dphy_drv_data r3568_dphy_drv_data = {
550 	.dev_name = "csi2dphy",
551 };
552 
553 static struct dphy_drv_data r3588_dcphy_drv_data = {
554 	.dev_name = "csi2dcphy",
555 };
556 
557 static const struct of_device_id rockchip_csi2_dphy_match_id[] = {
558 	{
559 		.compatible = "rockchip,rk3568-csi2-dphy",
560 		.data = &r3568_dphy_drv_data,
561 	},
562 	{
563 		.compatible = "rockchip,rk3588-csi2-dcphy",
564 		.data = &r3588_dcphy_drv_data,
565 	},
566 	{}
567 };
568 MODULE_DEVICE_TABLE(of, rockchip_csi2_dphy_match_id);
569 
rockchip_csi2_dphy_probe(struct platform_device * pdev)570 static int rockchip_csi2_dphy_probe(struct platform_device *pdev)
571 {
572 	struct device *dev = &pdev->dev;
573 	const struct of_device_id *of_id;
574 	struct csi2_dphy *csi2dphy;
575 	struct v4l2_subdev *sd;
576 	const struct dphy_drv_data *drv_data;
577 	int ret;
578 
579 	csi2dphy = devm_kzalloc(dev, sizeof(*csi2dphy), GFP_KERNEL);
580 	if (!csi2dphy)
581 		return -ENOMEM;
582 	csi2dphy->dev = dev;
583 
584 	of_id = of_match_device(rockchip_csi2_dphy_match_id, dev);
585 	if (!of_id)
586 		return -EINVAL;
587 	drv_data = of_id->data;
588 	csi2dphy->drv_data = drv_data;
589 	csi2dphy->phy_index = of_alias_get_id(dev->of_node, drv_data->dev_name);
590 	if (csi2dphy->phy_index < 0 || csi2dphy->phy_index >= PHY_MAX)
591 		csi2dphy->phy_index = 0;
592 	ret = rockchip_csi2_dphy_attach_hw(csi2dphy);
593 	if (ret) {
594 		dev_err(dev,
595 			"csi2 dphy hw can't be attached, register dphy%d failed!\n",
596 			csi2dphy->phy_index);
597 		return -ENODEV;
598 	}
599 
600 	sd = &csi2dphy->sd;
601 	mutex_init(&csi2dphy->mutex);
602 	v4l2_subdev_init(sd, &csi2_dphy_subdev_ops);
603 	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
604 	snprintf(sd->name, sizeof(sd->name),
605 		 "rockchip-csi2-dphy%d", csi2dphy->phy_index);
606 	sd->dev = dev;
607 
608 	platform_set_drvdata(pdev, &sd->entity);
609 
610 	ret = rockchip_csi2dphy_media_init(csi2dphy);
611 	if (ret < 0)
612 		goto detach_hw;
613 
614 	pm_runtime_enable(&pdev->dev);
615 
616 	dev_info(dev, "csi2 dphy%d probe successfully!\n", csi2dphy->phy_index);
617 
618 	return 0;
619 
620 detach_hw:
621 	mutex_destroy(&csi2dphy->mutex);
622 	rockchip_csi2_dphy_detach_hw(csi2dphy);
623 
624 	return 0;
625 }
626 
rockchip_csi2_dphy_remove(struct platform_device * pdev)627 static int rockchip_csi2_dphy_remove(struct platform_device *pdev)
628 {
629 	struct media_entity *me = platform_get_drvdata(pdev);
630 	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(me);
631 	struct csi2_dphy *dphy = to_csi2_dphy(sd);
632 
633 	media_entity_cleanup(&sd->entity);
634 
635 	pm_runtime_disable(&pdev->dev);
636 	mutex_destroy(&dphy->mutex);
637 	return 0;
638 }
639 
640 static const struct dev_pm_ops rockchip_csi2_dphy_pm_ops = {
641 	SET_RUNTIME_PM_OPS(csi2_dphy_runtime_suspend,
642 			   csi2_dphy_runtime_resume, NULL)
643 };
644 
645 struct platform_driver rockchip_csi2_dphy_driver = {
646 	.probe = rockchip_csi2_dphy_probe,
647 	.remove = rockchip_csi2_dphy_remove,
648 	.driver = {
649 		.name = "rockchip-csi2-dphy",
650 		.pm = &rockchip_csi2_dphy_pm_ops,
651 		.of_match_table = rockchip_csi2_dphy_match_id,
652 	},
653 };
654 module_platform_driver(rockchip_csi2_dphy_driver);
655 
656 MODULE_AUTHOR("Rockchip Camera/ISP team");
657 MODULE_DESCRIPTION("Rockchip MIPI CSI2 DPHY driver");
658 MODULE_LICENSE("GPL v2");
659