1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2023 Intel Corporation. All rights reserved. 4 * Intel Visual Sensing Controller CSI Linux driver 5 */ 6 7 /* 8 * To set ownership of CSI-2 link and to configure CSI-2 link, there 9 * are specific commands, which are sent via MEI protocol. The send 10 * command function uses "completion" as a synchronization mechanism. 11 * The response for command is received via a mei callback which wakes 12 * up the caller. There can be only one outstanding command at a time. 13 */ 14 15 #include <linux/completion.h> 16 #include <linux/delay.h> 17 #include <linux/kernel.h> 18 #include <linux/math64.h> 19 #include <linux/mei_cl_bus.h> 20 #include <linux/module.h> 21 #include <linux/mutex.h> 22 #include <linux/pm_runtime.h> 23 #include <linux/slab.h> 24 #include <linux/units.h> 25 #include <linux/uuid.h> 26 #include <linux/workqueue.h> 27 28 #include <media/v4l2-async.h> 29 #include <media/v4l2-ctrls.h> 30 #include <media/v4l2-fwnode.h> 31 #include <media/v4l2-subdev.h> 32 33 #define MEI_CSI_DRIVER_NAME "ivsc_csi" 34 #define MEI_CSI_ENTITY_NAME "Intel IVSC CSI" 35 36 #define MEI_CSI_LINK_FREQ_400MHZ 400000000ULL 37 38 /* the 5s used here is based on experiment */ 39 #define CSI_CMD_TIMEOUT (5 * HZ) 40 /* to setup CSI-2 link an extra delay needed and determined experimentally */ 41 #define CSI_FW_READY_DELAY_MS 100 42 /* link frequency unit is 100kHz */ 43 #define CSI_LINK_FREQ(x) ((u32)(div_u64(x, 100 * HZ_PER_KHZ))) 44 45 /* 46 * identify the command id supported by firmware 47 * IPC, as well as the privacy notification id 48 * used when processing privacy event. 49 */ 50 enum csi_cmd_id { 51 /* used to set csi ownership */ 52 CSI_SET_OWNER = 0, 53 54 /* used to configure CSI-2 link */ 55 CSI_SET_CONF = 2, 56 57 /* privacy notification id used when privacy state changes */ 58 CSI_PRIVACY_NOTIF = 6, 59 }; 60 61 /* CSI-2 link ownership definition */ 62 enum csi_link_owner { 63 CSI_LINK_IVSC, 64 CSI_LINK_HOST, 65 }; 66 67 /* privacy status definition */ 68 enum ivsc_privacy_status { 69 CSI_PRIVACY_OFF, 70 CSI_PRIVACY_ON, 71 CSI_PRIVACY_MAX, 72 }; 73 74 enum csi_pads { 75 CSI_PAD_SOURCE, 76 CSI_PAD_SINK, 77 CSI_NUM_PADS 78 }; 79 80 /* configuration of the CSI-2 link between host and IVSC */ 81 struct csi_link_cfg { 82 /* number of data lanes used on the CSI-2 link */ 83 u32 nr_of_lanes; 84 85 /* frequency of the CSI-2 link */ 86 u32 link_freq; 87 88 /* for future use */ 89 u32 rsvd[2]; 90 } __packed; 91 92 /* CSI command structure */ 93 struct csi_cmd { 94 u32 cmd_id; 95 union _cmd_param { 96 u32 param; 97 struct csi_link_cfg conf; 98 } param; 99 } __packed; 100 101 /* CSI notification structure */ 102 struct csi_notif { 103 u32 cmd_id; 104 int status; 105 union _resp_cont { 106 u32 cont; 107 struct csi_link_cfg conf; 108 } cont; 109 } __packed; 110 111 struct mei_csi { 112 struct mei_cl_device *cldev; 113 114 /* command response */ 115 struct csi_notif cmd_response; 116 /* used to wait for command response from firmware */ 117 struct completion cmd_completion; 118 /* protect command download */ 119 struct mutex lock; 120 121 struct v4l2_subdev subdev; 122 struct v4l2_subdev *remote; 123 struct v4l2_async_notifier notifier; 124 struct v4l2_ctrl_handler ctrl_handler; 125 struct v4l2_ctrl *freq_ctrl; 126 struct v4l2_ctrl *privacy_ctrl; 127 unsigned int remote_pad; 128 /* start streaming or not */ 129 int streaming; 130 131 struct media_pad pads[CSI_NUM_PADS]; 132 struct v4l2_mbus_framefmt format_mbus[CSI_NUM_PADS]; 133 134 /* number of data lanes used on the CSI-2 link */ 135 u32 nr_of_lanes; 136 /* frequency of the CSI-2 link */ 137 u64 link_freq; 138 139 /* privacy status */ 140 enum ivsc_privacy_status status; 141 }; 142 143 static const struct v4l2_mbus_framefmt mei_csi_format_mbus_default = { 144 .width = 1, 145 .height = 1, 146 .code = MEDIA_BUS_FMT_Y8_1X8, 147 .field = V4L2_FIELD_NONE, 148 }; 149 150 static s64 link_freq_menu_items[] = { 151 MEI_CSI_LINK_FREQ_400MHZ 152 }; 153 154 static inline struct mei_csi *notifier_to_csi(struct v4l2_async_notifier *n) 155 { 156 return container_of(n, struct mei_csi, notifier); 157 } 158 159 static inline struct mei_csi *sd_to_csi(struct v4l2_subdev *sd) 160 { 161 return container_of(sd, struct mei_csi, subdev); 162 } 163 164 static inline struct mei_csi *ctrl_to_csi(struct v4l2_ctrl *ctrl) 165 { 166 return container_of(ctrl->handler, struct mei_csi, ctrl_handler); 167 } 168 169 /* send a command to firmware and mutex must be held by caller */ 170 static int mei_csi_send(struct mei_csi *csi, u8 *buf, size_t len) 171 { 172 struct csi_cmd *cmd = (struct csi_cmd *)buf; 173 int ret; 174 175 reinit_completion(&csi->cmd_completion); 176 177 ret = mei_cldev_send(csi->cldev, buf, len); 178 if (ret < 0) 179 goto out; 180 181 ret = wait_for_completion_killable_timeout(&csi->cmd_completion, 182 CSI_CMD_TIMEOUT); 183 if (ret < 0) { 184 goto out; 185 } else if (!ret) { 186 ret = -ETIMEDOUT; 187 goto out; 188 } 189 190 /* command response status */ 191 ret = csi->cmd_response.status; 192 if (ret) { 193 ret = -EINVAL; 194 goto out; 195 } 196 197 if (csi->cmd_response.cmd_id != cmd->cmd_id) 198 ret = -EINVAL; 199 200 out: 201 return ret; 202 } 203 204 /* set CSI-2 link ownership */ 205 static int csi_set_link_owner(struct mei_csi *csi, enum csi_link_owner owner) 206 { 207 struct csi_cmd cmd = { 0 }; 208 size_t cmd_size; 209 int ret; 210 211 cmd.cmd_id = CSI_SET_OWNER; 212 cmd.param.param = owner; 213 cmd_size = sizeof(cmd.cmd_id) + sizeof(cmd.param.param); 214 215 mutex_lock(&csi->lock); 216 217 ret = mei_csi_send(csi, (u8 *)&cmd, cmd_size); 218 219 mutex_unlock(&csi->lock); 220 221 return ret; 222 } 223 224 /* configure CSI-2 link between host and IVSC */ 225 static int csi_set_link_cfg(struct mei_csi *csi) 226 { 227 struct csi_cmd cmd = { 0 }; 228 size_t cmd_size; 229 int ret; 230 231 cmd.cmd_id = CSI_SET_CONF; 232 cmd.param.conf.nr_of_lanes = csi->nr_of_lanes; 233 cmd.param.conf.link_freq = CSI_LINK_FREQ(csi->link_freq); 234 cmd_size = sizeof(cmd.cmd_id) + sizeof(cmd.param.conf); 235 236 mutex_lock(&csi->lock); 237 238 ret = mei_csi_send(csi, (u8 *)&cmd, cmd_size); 239 /* 240 * wait configuration ready if download success. placing 241 * delay under mutex is to make sure current command flow 242 * completed before starting a possible new one. 243 */ 244 if (!ret) 245 msleep(CSI_FW_READY_DELAY_MS); 246 247 mutex_unlock(&csi->lock); 248 249 return ret; 250 } 251 252 /* callback for receive */ 253 static void mei_csi_rx(struct mei_cl_device *cldev) 254 { 255 struct mei_csi *csi = mei_cldev_get_drvdata(cldev); 256 struct csi_notif notif = { 0 }; 257 int ret; 258 259 ret = mei_cldev_recv(cldev, (u8 *)¬if, sizeof(notif)); 260 if (ret < 0) { 261 dev_err(&cldev->dev, "recv error: %d\n", ret); 262 return; 263 } 264 265 switch (notif.cmd_id) { 266 case CSI_PRIVACY_NOTIF: 267 if (notif.cont.cont < CSI_PRIVACY_MAX) { 268 csi->status = notif.cont.cont; 269 v4l2_ctrl_s_ctrl(csi->privacy_ctrl, csi->status); 270 } 271 break; 272 case CSI_SET_OWNER: 273 case CSI_SET_CONF: 274 memcpy(&csi->cmd_response, ¬if, ret); 275 276 complete(&csi->cmd_completion); 277 break; 278 default: 279 break; 280 } 281 } 282 283 static int mei_csi_set_stream(struct v4l2_subdev *sd, int enable) 284 { 285 struct mei_csi *csi = sd_to_csi(sd); 286 s64 freq; 287 int ret; 288 289 if (enable && csi->streaming == 0) { 290 freq = v4l2_get_link_freq(csi->remote->ctrl_handler, 0, 0); 291 if (freq < 0) { 292 dev_err(&csi->cldev->dev, 293 "error %lld, invalid link_freq\n", freq); 294 ret = freq; 295 goto err; 296 } 297 csi->link_freq = freq; 298 299 /* switch CSI-2 link to host */ 300 ret = csi_set_link_owner(csi, CSI_LINK_HOST); 301 if (ret < 0) 302 goto err; 303 304 /* configure CSI-2 link */ 305 ret = csi_set_link_cfg(csi); 306 if (ret < 0) 307 goto err_switch; 308 309 ret = v4l2_subdev_call(csi->remote, video, s_stream, 1); 310 if (ret) 311 goto err_switch; 312 } else if (!enable && csi->streaming == 1) { 313 v4l2_subdev_call(csi->remote, video, s_stream, 0); 314 315 /* switch CSI-2 link to IVSC */ 316 ret = csi_set_link_owner(csi, CSI_LINK_IVSC); 317 if (ret < 0) 318 dev_warn(&csi->cldev->dev, 319 "failed to switch CSI2 link: %d\n", ret); 320 } 321 322 csi->streaming = enable; 323 324 return 0; 325 326 err_switch: 327 csi_set_link_owner(csi, CSI_LINK_IVSC); 328 329 err: 330 return ret; 331 } 332 333 static struct v4l2_mbus_framefmt * 334 mei_csi_get_pad_format(struct v4l2_subdev *sd, 335 struct v4l2_subdev_state *sd_state, 336 unsigned int pad, u32 which) 337 { 338 struct mei_csi *csi = sd_to_csi(sd); 339 340 switch (which) { 341 case V4L2_SUBDEV_FORMAT_TRY: 342 return v4l2_subdev_get_try_format(sd, sd_state, pad); 343 case V4L2_SUBDEV_FORMAT_ACTIVE: 344 return &csi->format_mbus[pad]; 345 default: 346 return NULL; 347 } 348 } 349 350 static int mei_csi_init_cfg(struct v4l2_subdev *sd, 351 struct v4l2_subdev_state *sd_state) 352 { 353 struct v4l2_mbus_framefmt *mbusformat; 354 struct mei_csi *csi = sd_to_csi(sd); 355 unsigned int i; 356 357 mutex_lock(&csi->lock); 358 359 for (i = 0; i < sd->entity.num_pads; i++) { 360 mbusformat = v4l2_subdev_get_try_format(sd, sd_state, i); 361 *mbusformat = mei_csi_format_mbus_default; 362 } 363 364 mutex_unlock(&csi->lock); 365 366 return 0; 367 } 368 369 static int mei_csi_get_fmt(struct v4l2_subdev *sd, 370 struct v4l2_subdev_state *sd_state, 371 struct v4l2_subdev_format *format) 372 { 373 struct v4l2_mbus_framefmt *mbusformat; 374 struct mei_csi *csi = sd_to_csi(sd); 375 376 mutex_lock(&csi->lock); 377 378 mbusformat = mei_csi_get_pad_format(sd, sd_state, format->pad, 379 format->which); 380 if (mbusformat) 381 format->format = *mbusformat; 382 383 mutex_unlock(&csi->lock); 384 385 return 0; 386 } 387 388 static int mei_csi_set_fmt(struct v4l2_subdev *sd, 389 struct v4l2_subdev_state *sd_state, 390 struct v4l2_subdev_format *format) 391 { 392 struct v4l2_mbus_framefmt *source_mbusformat; 393 struct v4l2_mbus_framefmt *mbusformat; 394 struct mei_csi *csi = sd_to_csi(sd); 395 struct media_pad *pad; 396 397 mbusformat = mei_csi_get_pad_format(sd, sd_state, format->pad, 398 format->which); 399 if (!mbusformat) 400 return -EINVAL; 401 402 source_mbusformat = mei_csi_get_pad_format(sd, sd_state, CSI_PAD_SOURCE, 403 format->which); 404 if (!source_mbusformat) 405 return -EINVAL; 406 407 v4l_bound_align_image(&format->format.width, 1, 65536, 0, 408 &format->format.height, 1, 65536, 0, 0); 409 410 switch (format->format.code) { 411 case MEDIA_BUS_FMT_RGB444_1X12: 412 case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE: 413 case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE: 414 case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE: 415 case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE: 416 case MEDIA_BUS_FMT_RGB565_1X16: 417 case MEDIA_BUS_FMT_BGR565_2X8_BE: 418 case MEDIA_BUS_FMT_BGR565_2X8_LE: 419 case MEDIA_BUS_FMT_RGB565_2X8_BE: 420 case MEDIA_BUS_FMT_RGB565_2X8_LE: 421 case MEDIA_BUS_FMT_RGB666_1X18: 422 case MEDIA_BUS_FMT_RBG888_1X24: 423 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 424 case MEDIA_BUS_FMT_BGR888_1X24: 425 case MEDIA_BUS_FMT_GBR888_1X24: 426 case MEDIA_BUS_FMT_RGB888_1X24: 427 case MEDIA_BUS_FMT_RGB888_2X12_BE: 428 case MEDIA_BUS_FMT_RGB888_2X12_LE: 429 case MEDIA_BUS_FMT_ARGB8888_1X32: 430 case MEDIA_BUS_FMT_RGB888_1X32_PADHI: 431 case MEDIA_BUS_FMT_RGB101010_1X30: 432 case MEDIA_BUS_FMT_RGB121212_1X36: 433 case MEDIA_BUS_FMT_RGB161616_1X48: 434 case MEDIA_BUS_FMT_Y8_1X8: 435 case MEDIA_BUS_FMT_UV8_1X8: 436 case MEDIA_BUS_FMT_UYVY8_1_5X8: 437 case MEDIA_BUS_FMT_VYUY8_1_5X8: 438 case MEDIA_BUS_FMT_YUYV8_1_5X8: 439 case MEDIA_BUS_FMT_YVYU8_1_5X8: 440 case MEDIA_BUS_FMT_UYVY8_2X8: 441 case MEDIA_BUS_FMT_VYUY8_2X8: 442 case MEDIA_BUS_FMT_YUYV8_2X8: 443 case MEDIA_BUS_FMT_YVYU8_2X8: 444 case MEDIA_BUS_FMT_Y10_1X10: 445 case MEDIA_BUS_FMT_UYVY10_2X10: 446 case MEDIA_BUS_FMT_VYUY10_2X10: 447 case MEDIA_BUS_FMT_YUYV10_2X10: 448 case MEDIA_BUS_FMT_YVYU10_2X10: 449 case MEDIA_BUS_FMT_Y12_1X12: 450 case MEDIA_BUS_FMT_UYVY12_2X12: 451 case MEDIA_BUS_FMT_VYUY12_2X12: 452 case MEDIA_BUS_FMT_YUYV12_2X12: 453 case MEDIA_BUS_FMT_YVYU12_2X12: 454 case MEDIA_BUS_FMT_UYVY8_1X16: 455 case MEDIA_BUS_FMT_VYUY8_1X16: 456 case MEDIA_BUS_FMT_YUYV8_1X16: 457 case MEDIA_BUS_FMT_YVYU8_1X16: 458 case MEDIA_BUS_FMT_YDYUYDYV8_1X16: 459 case MEDIA_BUS_FMT_UYVY10_1X20: 460 case MEDIA_BUS_FMT_VYUY10_1X20: 461 case MEDIA_BUS_FMT_YUYV10_1X20: 462 case MEDIA_BUS_FMT_YVYU10_1X20: 463 case MEDIA_BUS_FMT_VUY8_1X24: 464 case MEDIA_BUS_FMT_YUV8_1X24: 465 case MEDIA_BUS_FMT_UYYVYY8_0_5X24: 466 case MEDIA_BUS_FMT_UYVY12_1X24: 467 case MEDIA_BUS_FMT_VYUY12_1X24: 468 case MEDIA_BUS_FMT_YUYV12_1X24: 469 case MEDIA_BUS_FMT_YVYU12_1X24: 470 case MEDIA_BUS_FMT_YUV10_1X30: 471 case MEDIA_BUS_FMT_UYYVYY10_0_5X30: 472 case MEDIA_BUS_FMT_AYUV8_1X32: 473 case MEDIA_BUS_FMT_UYYVYY12_0_5X36: 474 case MEDIA_BUS_FMT_YUV12_1X36: 475 case MEDIA_BUS_FMT_YUV16_1X48: 476 case MEDIA_BUS_FMT_UYYVYY16_0_5X48: 477 case MEDIA_BUS_FMT_JPEG_1X8: 478 case MEDIA_BUS_FMT_AHSV8888_1X32: 479 case MEDIA_BUS_FMT_SBGGR8_1X8: 480 case MEDIA_BUS_FMT_SGBRG8_1X8: 481 case MEDIA_BUS_FMT_SGRBG8_1X8: 482 case MEDIA_BUS_FMT_SRGGB8_1X8: 483 case MEDIA_BUS_FMT_SBGGR10_1X10: 484 case MEDIA_BUS_FMT_SGBRG10_1X10: 485 case MEDIA_BUS_FMT_SGRBG10_1X10: 486 case MEDIA_BUS_FMT_SRGGB10_1X10: 487 case MEDIA_BUS_FMT_SBGGR12_1X12: 488 case MEDIA_BUS_FMT_SGBRG12_1X12: 489 case MEDIA_BUS_FMT_SGRBG12_1X12: 490 case MEDIA_BUS_FMT_SRGGB12_1X12: 491 case MEDIA_BUS_FMT_SBGGR14_1X14: 492 case MEDIA_BUS_FMT_SGBRG14_1X14: 493 case MEDIA_BUS_FMT_SGRBG14_1X14: 494 case MEDIA_BUS_FMT_SRGGB14_1X14: 495 case MEDIA_BUS_FMT_SBGGR16_1X16: 496 case MEDIA_BUS_FMT_SGBRG16_1X16: 497 case MEDIA_BUS_FMT_SGRBG16_1X16: 498 case MEDIA_BUS_FMT_SRGGB16_1X16: 499 break; 500 default: 501 format->format.code = MEDIA_BUS_FMT_Y8_1X8; 502 break; 503 } 504 505 if (format->format.field == V4L2_FIELD_ANY) 506 format->format.field = V4L2_FIELD_NONE; 507 508 mutex_lock(&csi->lock); 509 510 pad = &csi->pads[format->pad]; 511 if (pad->flags & MEDIA_PAD_FL_SOURCE) 512 format->format = csi->format_mbus[CSI_PAD_SINK]; 513 514 *mbusformat = format->format; 515 516 if (pad->flags & MEDIA_PAD_FL_SINK) 517 *source_mbusformat = format->format; 518 519 mutex_unlock(&csi->lock); 520 521 return 0; 522 } 523 524 static int mei_csi_g_volatile_ctrl(struct v4l2_ctrl *ctrl) 525 { 526 struct mei_csi *csi = ctrl_to_csi(ctrl); 527 s64 freq; 528 529 if (ctrl->id == V4L2_CID_LINK_FREQ) { 530 if (!csi->remote) 531 return -EINVAL; 532 533 freq = v4l2_get_link_freq(csi->remote->ctrl_handler, 0, 0); 534 if (freq < 0) { 535 dev_err(&csi->cldev->dev, 536 "error %lld, invalid link_freq\n", freq); 537 return -EINVAL; 538 } 539 540 link_freq_menu_items[0] = freq; 541 ctrl->val = 0; 542 543 return 0; 544 } 545 546 return -EINVAL; 547 } 548 549 static const struct v4l2_ctrl_ops mei_csi_ctrl_ops = { 550 .g_volatile_ctrl = mei_csi_g_volatile_ctrl, 551 }; 552 553 static const struct v4l2_subdev_video_ops mei_csi_video_ops = { 554 .s_stream = mei_csi_set_stream, 555 }; 556 557 static const struct v4l2_subdev_pad_ops mei_csi_pad_ops = { 558 .init_cfg = mei_csi_init_cfg, 559 .get_fmt = mei_csi_get_fmt, 560 .set_fmt = mei_csi_set_fmt, 561 }; 562 563 static const struct v4l2_subdev_ops mei_csi_subdev_ops = { 564 .video = &mei_csi_video_ops, 565 .pad = &mei_csi_pad_ops, 566 }; 567 568 static const struct media_entity_operations mei_csi_entity_ops = { 569 .link_validate = v4l2_subdev_link_validate, 570 }; 571 572 static int mei_csi_notify_bound(struct v4l2_async_notifier *notifier, 573 struct v4l2_subdev *subdev, 574 struct v4l2_async_connection *asd) 575 { 576 struct mei_csi *csi = notifier_to_csi(notifier); 577 int pad; 578 579 pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode, 580 MEDIA_PAD_FL_SOURCE); 581 if (pad < 0) 582 return pad; 583 584 csi->remote = subdev; 585 csi->remote_pad = pad; 586 587 return media_create_pad_link(&subdev->entity, pad, 588 &csi->subdev.entity, 1, 589 MEDIA_LNK_FL_ENABLED | 590 MEDIA_LNK_FL_IMMUTABLE); 591 } 592 593 static void mei_csi_notify_unbind(struct v4l2_async_notifier *notifier, 594 struct v4l2_subdev *subdev, 595 struct v4l2_async_connection *asd) 596 { 597 struct mei_csi *csi = notifier_to_csi(notifier); 598 599 csi->remote = NULL; 600 } 601 602 static const struct v4l2_async_notifier_operations mei_csi_notify_ops = { 603 .bound = mei_csi_notify_bound, 604 .unbind = mei_csi_notify_unbind, 605 }; 606 607 static int mei_csi_init_controls(struct mei_csi *csi) 608 { 609 u32 max; 610 int ret; 611 612 ret = v4l2_ctrl_handler_init(&csi->ctrl_handler, 2); 613 if (ret) 614 return ret; 615 616 csi->ctrl_handler.lock = &csi->lock; 617 618 max = ARRAY_SIZE(link_freq_menu_items) - 1; 619 csi->freq_ctrl = v4l2_ctrl_new_int_menu(&csi->ctrl_handler, 620 &mei_csi_ctrl_ops, 621 V4L2_CID_LINK_FREQ, 622 max, 623 0, 624 link_freq_menu_items); 625 if (csi->freq_ctrl) 626 csi->freq_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY | 627 V4L2_CTRL_FLAG_VOLATILE; 628 629 csi->privacy_ctrl = v4l2_ctrl_new_std(&csi->ctrl_handler, NULL, 630 V4L2_CID_PRIVACY, 0, 1, 1, 0); 631 if (csi->privacy_ctrl) 632 csi->privacy_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; 633 634 if (csi->ctrl_handler.error) 635 return csi->ctrl_handler.error; 636 637 csi->subdev.ctrl_handler = &csi->ctrl_handler; 638 639 return 0; 640 } 641 642 static int mei_csi_parse_firmware(struct mei_csi *csi) 643 { 644 struct v4l2_fwnode_endpoint v4l2_ep = { 645 .bus_type = V4L2_MBUS_CSI2_DPHY, 646 }; 647 struct device *dev = &csi->cldev->dev; 648 struct v4l2_async_connection *asd; 649 struct fwnode_handle *fwnode; 650 struct fwnode_handle *ep; 651 int ret; 652 653 ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), 0, 0, 0); 654 if (!ep) { 655 dev_err(dev, "not connected to subdevice\n"); 656 return -EINVAL; 657 } 658 659 ret = v4l2_fwnode_endpoint_parse(ep, &v4l2_ep); 660 if (ret) { 661 dev_err(dev, "could not parse v4l2 endpoint\n"); 662 fwnode_handle_put(ep); 663 return -EINVAL; 664 } 665 666 fwnode = fwnode_graph_get_remote_endpoint(ep); 667 fwnode_handle_put(ep); 668 669 v4l2_async_subdev_nf_init(&csi->notifier, &csi->subdev); 670 csi->notifier.ops = &mei_csi_notify_ops; 671 672 asd = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode, 673 struct v4l2_async_connection); 674 if (IS_ERR(asd)) { 675 fwnode_handle_put(fwnode); 676 return PTR_ERR(asd); 677 } 678 679 ret = v4l2_fwnode_endpoint_alloc_parse(fwnode, &v4l2_ep); 680 fwnode_handle_put(fwnode); 681 if (ret) 682 return ret; 683 csi->nr_of_lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes; 684 685 ret = v4l2_async_nf_register(&csi->notifier); 686 if (ret) 687 v4l2_async_nf_cleanup(&csi->notifier); 688 689 v4l2_fwnode_endpoint_free(&v4l2_ep); 690 691 return ret; 692 } 693 694 static int mei_csi_probe(struct mei_cl_device *cldev, 695 const struct mei_cl_device_id *id) 696 { 697 struct device *dev = &cldev->dev; 698 struct mei_csi *csi; 699 int ret; 700 701 if (!dev_fwnode(dev)) 702 return -EPROBE_DEFER; 703 704 csi = devm_kzalloc(dev, sizeof(struct mei_csi), GFP_KERNEL); 705 if (!csi) 706 return -ENOMEM; 707 708 csi->cldev = cldev; 709 mutex_init(&csi->lock); 710 init_completion(&csi->cmd_completion); 711 712 mei_cldev_set_drvdata(cldev, csi); 713 714 ret = mei_cldev_enable(cldev); 715 if (ret < 0) { 716 dev_err(dev, "mei_cldev_enable failed: %d\n", ret); 717 goto destroy_mutex; 718 } 719 720 ret = mei_cldev_register_rx_cb(cldev, mei_csi_rx); 721 if (ret) { 722 dev_err(dev, "event cb registration failed: %d\n", ret); 723 goto err_disable; 724 } 725 726 ret = mei_csi_parse_firmware(csi); 727 if (ret) 728 goto err_disable; 729 730 csi->subdev.dev = &cldev->dev; 731 v4l2_subdev_init(&csi->subdev, &mei_csi_subdev_ops); 732 v4l2_set_subdevdata(&csi->subdev, csi); 733 csi->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | 734 V4L2_SUBDEV_FL_HAS_EVENTS; 735 csi->subdev.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE; 736 csi->subdev.entity.ops = &mei_csi_entity_ops; 737 738 snprintf(csi->subdev.name, sizeof(csi->subdev.name), 739 MEI_CSI_ENTITY_NAME); 740 741 ret = mei_csi_init_controls(csi); 742 if (ret) 743 goto err_ctrl_handler; 744 745 csi->format_mbus[CSI_PAD_SOURCE] = mei_csi_format_mbus_default; 746 csi->format_mbus[CSI_PAD_SINK] = mei_csi_format_mbus_default; 747 748 csi->pads[CSI_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; 749 csi->pads[CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK; 750 ret = media_entity_pads_init(&csi->subdev.entity, CSI_NUM_PADS, 751 csi->pads); 752 if (ret) 753 goto err_ctrl_handler; 754 755 ret = v4l2_subdev_init_finalize(&csi->subdev); 756 if (ret < 0) 757 goto err_entity; 758 759 ret = v4l2_async_register_subdev(&csi->subdev); 760 if (ret < 0) 761 goto err_subdev; 762 763 pm_runtime_enable(&cldev->dev); 764 765 return 0; 766 767 err_subdev: 768 v4l2_subdev_cleanup(&csi->subdev); 769 770 err_entity: 771 media_entity_cleanup(&csi->subdev.entity); 772 773 err_ctrl_handler: 774 v4l2_ctrl_handler_free(&csi->ctrl_handler); 775 v4l2_async_nf_unregister(&csi->notifier); 776 v4l2_async_nf_cleanup(&csi->notifier); 777 778 err_disable: 779 mei_cldev_disable(cldev); 780 781 destroy_mutex: 782 mutex_destroy(&csi->lock); 783 784 return ret; 785 } 786 787 static void mei_csi_remove(struct mei_cl_device *cldev) 788 { 789 struct mei_csi *csi = mei_cldev_get_drvdata(cldev); 790 791 v4l2_async_nf_unregister(&csi->notifier); 792 v4l2_async_nf_cleanup(&csi->notifier); 793 v4l2_ctrl_handler_free(&csi->ctrl_handler); 794 v4l2_async_unregister_subdev(&csi->subdev); 795 v4l2_subdev_cleanup(&csi->subdev); 796 media_entity_cleanup(&csi->subdev.entity); 797 798 pm_runtime_disable(&cldev->dev); 799 800 mutex_destroy(&csi->lock); 801 } 802 803 #define MEI_CSI_UUID UUID_LE(0x92335FCF, 0x3203, 0x4472, \ 804 0xAF, 0x93, 0x7b, 0x44, 0x53, 0xAC, 0x29, 0xDA) 805 806 static const struct mei_cl_device_id mei_csi_tbl[] = { 807 { MEI_CSI_DRIVER_NAME, MEI_CSI_UUID, MEI_CL_VERSION_ANY }, 808 { /* sentinel */ } 809 }; 810 MODULE_DEVICE_TABLE(mei, mei_csi_tbl); 811 812 static struct mei_cl_driver mei_csi_driver = { 813 .id_table = mei_csi_tbl, 814 .name = MEI_CSI_DRIVER_NAME, 815 816 .probe = mei_csi_probe, 817 .remove = mei_csi_remove, 818 }; 819 820 module_mei_cl_driver(mei_csi_driver); 821 822 MODULE_AUTHOR("Wentong Wu <wentong.wu@intel.com>"); 823 MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>"); 824 MODULE_DESCRIPTION("Device driver for IVSC CSI"); 825 MODULE_LICENSE("GPL"); 826