0001
0002
0003
0004
0005
0006 #include <linux/clk.h>
0007 #include <linux/clk/tegra.h>
0008 #include <linux/device.h>
0009 #include <linux/host1x.h>
0010 #include <linux/module.h>
0011 #include <linux/of.h>
0012 #include <linux/of_graph.h>
0013 #include <linux/of_device.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/pm_runtime.h>
0016
0017 #include <media/v4l2-fwnode.h>
0018
0019 #include "csi.h"
0020 #include "video.h"
0021
0022 #define MHZ 1000000
0023
0024 static inline struct tegra_csi *
0025 host1x_client_to_csi(struct host1x_client *client)
0026 {
0027 return container_of(client, struct tegra_csi, client);
0028 }
0029
0030 static inline struct tegra_csi_channel *to_csi_chan(struct v4l2_subdev *subdev)
0031 {
0032 return container_of(subdev, struct tegra_csi_channel, subdev);
0033 }
0034
0035
0036
0037
0038
0039
0040 static const struct v4l2_mbus_framefmt tegra_csi_tpg_fmts[] = {
0041 {
0042 TEGRA_DEF_WIDTH,
0043 TEGRA_DEF_HEIGHT,
0044 MEDIA_BUS_FMT_SRGGB10_1X10,
0045 V4L2_FIELD_NONE,
0046 V4L2_COLORSPACE_SRGB
0047 },
0048 {
0049 TEGRA_DEF_WIDTH,
0050 TEGRA_DEF_HEIGHT,
0051 MEDIA_BUS_FMT_RGB888_1X32_PADHI,
0052 V4L2_FIELD_NONE,
0053 V4L2_COLORSPACE_SRGB
0054 },
0055 };
0056
0057 static const struct v4l2_frmsize_discrete tegra_csi_tpg_sizes[] = {
0058 { 1280, 720 },
0059 { 1920, 1080 },
0060 { 3840, 2160 },
0061 };
0062
0063
0064
0065
0066 static int csi_enum_bus_code(struct v4l2_subdev *subdev,
0067 struct v4l2_subdev_state *sd_state,
0068 struct v4l2_subdev_mbus_code_enum *code)
0069 {
0070 if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
0071 return -ENOIOCTLCMD;
0072
0073 if (code->index >= ARRAY_SIZE(tegra_csi_tpg_fmts))
0074 return -EINVAL;
0075
0076 code->code = tegra_csi_tpg_fmts[code->index].code;
0077
0078 return 0;
0079 }
0080
0081 static int csi_get_format(struct v4l2_subdev *subdev,
0082 struct v4l2_subdev_state *sd_state,
0083 struct v4l2_subdev_format *fmt)
0084 {
0085 struct tegra_csi_channel *csi_chan = to_csi_chan(subdev);
0086
0087 if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
0088 return -ENOIOCTLCMD;
0089
0090 fmt->format = csi_chan->format;
0091
0092 return 0;
0093 }
0094
0095 static int csi_get_frmrate_table_index(struct tegra_csi *csi, u32 code,
0096 u32 width, u32 height)
0097 {
0098 const struct tpg_framerate *frmrate;
0099 unsigned int i;
0100
0101 frmrate = csi->soc->tpg_frmrate_table;
0102 for (i = 0; i < csi->soc->tpg_frmrate_table_size; i++) {
0103 if (frmrate[i].code == code &&
0104 frmrate[i].frmsize.width == width &&
0105 frmrate[i].frmsize.height == height) {
0106 return i;
0107 }
0108 }
0109
0110 return -EINVAL;
0111 }
0112
0113 static void csi_chan_update_blank_intervals(struct tegra_csi_channel *csi_chan,
0114 u32 code, u32 width, u32 height)
0115 {
0116 struct tegra_csi *csi = csi_chan->csi;
0117 const struct tpg_framerate *frmrate = csi->soc->tpg_frmrate_table;
0118 int index;
0119
0120 index = csi_get_frmrate_table_index(csi_chan->csi, code,
0121 width, height);
0122 if (index >= 0) {
0123 csi_chan->h_blank = frmrate[index].h_blank;
0124 csi_chan->v_blank = frmrate[index].v_blank;
0125 csi_chan->framerate = frmrate[index].framerate;
0126 }
0127 }
0128
0129 static int csi_enum_framesizes(struct v4l2_subdev *subdev,
0130 struct v4l2_subdev_state *sd_state,
0131 struct v4l2_subdev_frame_size_enum *fse)
0132 {
0133 unsigned int i;
0134
0135 if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
0136 return -ENOIOCTLCMD;
0137
0138 if (fse->index >= ARRAY_SIZE(tegra_csi_tpg_sizes))
0139 return -EINVAL;
0140
0141 for (i = 0; i < ARRAY_SIZE(tegra_csi_tpg_fmts); i++)
0142 if (fse->code == tegra_csi_tpg_fmts[i].code)
0143 break;
0144
0145 if (i == ARRAY_SIZE(tegra_csi_tpg_fmts))
0146 return -EINVAL;
0147
0148 fse->min_width = tegra_csi_tpg_sizes[fse->index].width;
0149 fse->max_width = tegra_csi_tpg_sizes[fse->index].width;
0150 fse->min_height = tegra_csi_tpg_sizes[fse->index].height;
0151 fse->max_height = tegra_csi_tpg_sizes[fse->index].height;
0152
0153 return 0;
0154 }
0155
0156 static int csi_enum_frameintervals(struct v4l2_subdev *subdev,
0157 struct v4l2_subdev_state *sd_state,
0158 struct v4l2_subdev_frame_interval_enum *fie)
0159 {
0160 struct tegra_csi_channel *csi_chan = to_csi_chan(subdev);
0161 struct tegra_csi *csi = csi_chan->csi;
0162 const struct tpg_framerate *frmrate = csi->soc->tpg_frmrate_table;
0163 int index;
0164
0165 if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
0166 return -ENOIOCTLCMD;
0167
0168
0169 if (fie->index > 0)
0170 return -EINVAL;
0171
0172 index = csi_get_frmrate_table_index(csi_chan->csi, fie->code,
0173 fie->width, fie->height);
0174 if (index < 0)
0175 return -EINVAL;
0176
0177 fie->interval.numerator = 1;
0178 fie->interval.denominator = frmrate[index].framerate;
0179
0180 return 0;
0181 }
0182
0183 static int csi_set_format(struct v4l2_subdev *subdev,
0184 struct v4l2_subdev_state *sd_state,
0185 struct v4l2_subdev_format *fmt)
0186 {
0187 struct tegra_csi_channel *csi_chan = to_csi_chan(subdev);
0188 struct v4l2_mbus_framefmt *format = &fmt->format;
0189 const struct v4l2_frmsize_discrete *sizes;
0190 unsigned int i;
0191
0192 if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
0193 return -ENOIOCTLCMD;
0194
0195 sizes = v4l2_find_nearest_size(tegra_csi_tpg_sizes,
0196 ARRAY_SIZE(tegra_csi_tpg_sizes),
0197 width, height,
0198 format->width, format->width);
0199 format->width = sizes->width;
0200 format->height = sizes->height;
0201
0202 for (i = 0; i < ARRAY_SIZE(tegra_csi_tpg_fmts); i++)
0203 if (format->code == tegra_csi_tpg_fmts[i].code)
0204 break;
0205
0206 if (i == ARRAY_SIZE(tegra_csi_tpg_fmts))
0207 i = 0;
0208
0209 format->code = tegra_csi_tpg_fmts[i].code;
0210 format->field = V4L2_FIELD_NONE;
0211
0212 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
0213 return 0;
0214
0215
0216 csi_chan_update_blank_intervals(csi_chan, format->code,
0217 format->width, format->height);
0218 csi_chan->format = *format;
0219
0220 return 0;
0221 }
0222
0223
0224
0225
0226 static int tegra_csi_g_frame_interval(struct v4l2_subdev *subdev,
0227 struct v4l2_subdev_frame_interval *vfi)
0228 {
0229 struct tegra_csi_channel *csi_chan = to_csi_chan(subdev);
0230
0231 if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
0232 return -ENOIOCTLCMD;
0233
0234 vfi->interval.numerator = 1;
0235 vfi->interval.denominator = csi_chan->framerate;
0236
0237 return 0;
0238 }
0239
0240 static unsigned int csi_get_pixel_rate(struct tegra_csi_channel *csi_chan)
0241 {
0242 struct tegra_vi_channel *chan;
0243 struct v4l2_subdev *src_subdev;
0244 struct v4l2_ctrl *ctrl;
0245
0246 chan = v4l2_get_subdev_hostdata(&csi_chan->subdev);
0247 src_subdev = tegra_channel_get_remote_source_subdev(chan);
0248 ctrl = v4l2_ctrl_find(src_subdev->ctrl_handler, V4L2_CID_PIXEL_RATE);
0249 if (ctrl)
0250 return v4l2_ctrl_g_ctrl_int64(ctrl);
0251
0252 return 0;
0253 }
0254
0255 void tegra_csi_calc_settle_time(struct tegra_csi_channel *csi_chan,
0256 u8 csi_port_num,
0257 u8 *clk_settle_time,
0258 u8 *ths_settle_time)
0259 {
0260 struct tegra_csi *csi = csi_chan->csi;
0261 unsigned int cil_clk_mhz;
0262 unsigned int pix_clk_mhz;
0263 int clk_idx = (csi_port_num >> 1) + 1;
0264
0265 cil_clk_mhz = clk_get_rate(csi->clks[clk_idx].clk) / MHZ;
0266 pix_clk_mhz = csi_get_pixel_rate(csi_chan) / MHZ;
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 *clk_settle_time = ((95 + 300) * cil_clk_mhz - 14000) / 2000;
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289 if (pix_clk_mhz)
0290 *ths_settle_time = (115 * cil_clk_mhz + 8000 * cil_clk_mhz
0291 / (2 * pix_clk_mhz) - 5000) / 1000;
0292 }
0293
0294 static int tegra_csi_enable_stream(struct v4l2_subdev *subdev)
0295 {
0296 struct tegra_vi_channel *chan = v4l2_get_subdev_hostdata(subdev);
0297 struct tegra_csi_channel *csi_chan = to_csi_chan(subdev);
0298 struct tegra_csi *csi = csi_chan->csi;
0299 int ret, err;
0300
0301 ret = pm_runtime_resume_and_get(csi->dev);
0302 if (ret < 0) {
0303 dev_err(csi->dev, "failed to get runtime PM: %d\n", ret);
0304 return ret;
0305 }
0306
0307 if (csi_chan->mipi) {
0308 ret = tegra_mipi_enable(csi_chan->mipi);
0309 if (ret < 0) {
0310 dev_err(csi->dev,
0311 "failed to enable MIPI pads: %d\n", ret);
0312 goto rpm_put;
0313 }
0314
0315
0316
0317
0318
0319
0320
0321
0322 ret = tegra_mipi_start_calibration(csi_chan->mipi);
0323 if (ret < 0) {
0324 dev_err(csi->dev,
0325 "failed to start MIPI calibration: %d\n", ret);
0326 goto disable_mipi;
0327 }
0328 }
0329
0330 csi_chan->pg_mode = chan->pg_mode;
0331 ret = csi->ops->csi_start_streaming(csi_chan);
0332 if (ret < 0)
0333 goto finish_calibration;
0334
0335 return 0;
0336
0337 finish_calibration:
0338 if (csi_chan->mipi)
0339 tegra_mipi_finish_calibration(csi_chan->mipi);
0340 disable_mipi:
0341 if (csi_chan->mipi) {
0342 err = tegra_mipi_disable(csi_chan->mipi);
0343 if (err < 0)
0344 dev_err(csi->dev,
0345 "failed to disable MIPI pads: %d\n", err);
0346 }
0347
0348 rpm_put:
0349 pm_runtime_put(csi->dev);
0350 return ret;
0351 }
0352
0353 static int tegra_csi_disable_stream(struct v4l2_subdev *subdev)
0354 {
0355 struct tegra_csi_channel *csi_chan = to_csi_chan(subdev);
0356 struct tegra_csi *csi = csi_chan->csi;
0357 int err;
0358
0359 csi->ops->csi_stop_streaming(csi_chan);
0360
0361 if (csi_chan->mipi) {
0362 err = tegra_mipi_disable(csi_chan->mipi);
0363 if (err < 0)
0364 dev_err(csi->dev,
0365 "failed to disable MIPI pads: %d\n", err);
0366 }
0367
0368 pm_runtime_put(csi->dev);
0369
0370 return 0;
0371 }
0372
0373 static int tegra_csi_s_stream(struct v4l2_subdev *subdev, int enable)
0374 {
0375 int ret;
0376
0377 if (enable)
0378 ret = tegra_csi_enable_stream(subdev);
0379 else
0380 ret = tegra_csi_disable_stream(subdev);
0381
0382 return ret;
0383 }
0384
0385
0386
0387
0388 static const struct v4l2_subdev_video_ops tegra_csi_video_ops = {
0389 .s_stream = tegra_csi_s_stream,
0390 .g_frame_interval = tegra_csi_g_frame_interval,
0391 .s_frame_interval = tegra_csi_g_frame_interval,
0392 };
0393
0394 static const struct v4l2_subdev_pad_ops tegra_csi_pad_ops = {
0395 .enum_mbus_code = csi_enum_bus_code,
0396 .enum_frame_size = csi_enum_framesizes,
0397 .enum_frame_interval = csi_enum_frameintervals,
0398 .get_fmt = csi_get_format,
0399 .set_fmt = csi_set_format,
0400 };
0401
0402 static const struct v4l2_subdev_ops tegra_csi_ops = {
0403 .video = &tegra_csi_video_ops,
0404 .pad = &tegra_csi_pad_ops,
0405 };
0406
0407 static int tegra_csi_channel_alloc(struct tegra_csi *csi,
0408 struct device_node *node,
0409 unsigned int port_num, unsigned int lanes,
0410 unsigned int num_pads)
0411 {
0412 struct tegra_csi_channel *chan;
0413 int ret = 0, i;
0414
0415 chan = kzalloc(sizeof(*chan), GFP_KERNEL);
0416 if (!chan)
0417 return -ENOMEM;
0418
0419 list_add_tail(&chan->list, &csi->csi_chans);
0420 chan->csi = csi;
0421
0422
0423
0424
0425 if (lanes <= CSI_LANES_PER_BRICK) {
0426 chan->numlanes = lanes;
0427 chan->numgangports = 1;
0428 } else {
0429 chan->numlanes = CSI_LANES_PER_BRICK;
0430 chan->numgangports = lanes / CSI_LANES_PER_BRICK;
0431 }
0432
0433 for (i = 0; i < chan->numgangports; i++)
0434 chan->csi_port_nums[i] = port_num + i * CSI_PORTS_PER_BRICK;
0435
0436 chan->of_node = node;
0437 chan->numpads = num_pads;
0438 if (num_pads & 0x2) {
0439 chan->pads[0].flags = MEDIA_PAD_FL_SINK;
0440 chan->pads[1].flags = MEDIA_PAD_FL_SOURCE;
0441 } else {
0442 chan->pads[0].flags = MEDIA_PAD_FL_SOURCE;
0443 }
0444
0445 if (IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
0446 return 0;
0447
0448 chan->mipi = tegra_mipi_request(csi->dev, node);
0449 if (IS_ERR(chan->mipi)) {
0450 ret = PTR_ERR(chan->mipi);
0451 dev_err(csi->dev, "failed to get mipi device: %d\n", ret);
0452 }
0453
0454 return ret;
0455 }
0456
0457 static int tegra_csi_tpg_channels_alloc(struct tegra_csi *csi)
0458 {
0459 struct device_node *node = csi->dev->of_node;
0460 unsigned int port_num;
0461 unsigned int tpg_channels = csi->soc->csi_max_channels;
0462 int ret;
0463
0464
0465 for (port_num = 0; port_num < tpg_channels; port_num++) {
0466 ret = tegra_csi_channel_alloc(csi, node, port_num, 2, 1);
0467 if (ret < 0)
0468 return ret;
0469 }
0470
0471 return 0;
0472 }
0473
0474 static int tegra_csi_channels_alloc(struct tegra_csi *csi)
0475 {
0476 struct device_node *node = csi->dev->of_node;
0477 struct v4l2_fwnode_endpoint v4l2_ep = {
0478 .bus_type = V4L2_MBUS_CSI2_DPHY
0479 };
0480 struct fwnode_handle *fwh;
0481 struct device_node *channel;
0482 struct device_node *ep;
0483 unsigned int lanes, portno, num_pads;
0484 int ret;
0485
0486 for_each_child_of_node(node, channel) {
0487 if (!of_node_name_eq(channel, "channel"))
0488 continue;
0489
0490 ret = of_property_read_u32(channel, "reg", &portno);
0491 if (ret < 0)
0492 continue;
0493
0494 if (portno >= csi->soc->csi_max_channels) {
0495 dev_err(csi->dev, "invalid port num %d for %pOF\n",
0496 portno, channel);
0497 ret = -EINVAL;
0498 goto err_node_put;
0499 }
0500
0501 ep = of_graph_get_endpoint_by_regs(channel, 0, 0);
0502 if (!ep)
0503 continue;
0504
0505 fwh = of_fwnode_handle(ep);
0506 ret = v4l2_fwnode_endpoint_parse(fwh, &v4l2_ep);
0507 of_node_put(ep);
0508 if (ret) {
0509 dev_err(csi->dev,
0510 "failed to parse v4l2 endpoint for %pOF: %d\n",
0511 channel, ret);
0512 goto err_node_put;
0513 }
0514
0515 lanes = v4l2_ep.bus.mipi_csi2.num_data_lanes;
0516
0517
0518
0519
0520
0521
0522 if (!lanes || ((lanes & (lanes - 1)) != 0) ||
0523 (lanes > CSI_LANES_PER_BRICK && ((portno & 1) != 0))) {
0524 dev_err(csi->dev, "invalid data-lanes %d for %pOF\n",
0525 lanes, channel);
0526 ret = -EINVAL;
0527 goto err_node_put;
0528 }
0529
0530 num_pads = of_graph_get_endpoint_count(channel);
0531 if (num_pads == TEGRA_CSI_PADS_NUM) {
0532 ret = tegra_csi_channel_alloc(csi, channel, portno,
0533 lanes, num_pads);
0534 if (ret < 0)
0535 goto err_node_put;
0536 }
0537 }
0538
0539 return 0;
0540
0541 err_node_put:
0542 of_node_put(channel);
0543 return ret;
0544 }
0545
0546 static int tegra_csi_channel_init(struct tegra_csi_channel *chan)
0547 {
0548 struct tegra_csi *csi = chan->csi;
0549 struct v4l2_subdev *subdev;
0550 int ret;
0551
0552
0553 chan->format.code = MEDIA_BUS_FMT_SRGGB10_1X10;
0554 chan->format.field = V4L2_FIELD_NONE;
0555 chan->format.colorspace = V4L2_COLORSPACE_SRGB;
0556 chan->format.width = TEGRA_DEF_WIDTH;
0557 chan->format.height = TEGRA_DEF_HEIGHT;
0558 csi_chan_update_blank_intervals(chan, chan->format.code,
0559 chan->format.width,
0560 chan->format.height);
0561
0562 subdev = &chan->subdev;
0563 v4l2_subdev_init(subdev, &tegra_csi_ops);
0564 subdev->dev = csi->dev;
0565 if (IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
0566 snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "%s-%d", "tpg",
0567 chan->csi_port_nums[0]);
0568 else
0569 snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "%s",
0570 kbasename(chan->of_node->full_name));
0571
0572 v4l2_set_subdevdata(subdev, chan);
0573 subdev->fwnode = of_fwnode_handle(chan->of_node);
0574 subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
0575
0576
0577 ret = media_entity_pads_init(&subdev->entity, chan->numpads,
0578 chan->pads);
0579 if (ret < 0) {
0580 dev_err(csi->dev,
0581 "failed to initialize media entity: %d\n", ret);
0582 subdev->dev = NULL;
0583 return ret;
0584 }
0585
0586 if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG)) {
0587 ret = v4l2_async_register_subdev(subdev);
0588 if (ret < 0) {
0589 dev_err(csi->dev,
0590 "failed to register subdev: %d\n", ret);
0591 return ret;
0592 }
0593 }
0594
0595 return 0;
0596 }
0597
0598 void tegra_csi_error_recover(struct v4l2_subdev *sd)
0599 {
0600 struct tegra_csi_channel *csi_chan = to_csi_chan(sd);
0601 struct tegra_csi *csi = csi_chan->csi;
0602
0603
0604 csi->ops->csi_stop_streaming(csi_chan);
0605 csi->ops->csi_err_recover(csi_chan);
0606 csi->ops->csi_start_streaming(csi_chan);
0607 }
0608
0609 static int tegra_csi_channels_init(struct tegra_csi *csi)
0610 {
0611 struct tegra_csi_channel *chan;
0612 int ret;
0613
0614 list_for_each_entry(chan, &csi->csi_chans, list) {
0615 ret = tegra_csi_channel_init(chan);
0616 if (ret) {
0617 dev_err(csi->dev,
0618 "failed to initialize channel-%d: %d\n",
0619 chan->csi_port_nums[0], ret);
0620 return ret;
0621 }
0622 }
0623
0624 return 0;
0625 }
0626
0627 static void tegra_csi_channels_cleanup(struct tegra_csi *csi)
0628 {
0629 struct v4l2_subdev *subdev;
0630 struct tegra_csi_channel *chan, *tmp;
0631
0632 list_for_each_entry_safe(chan, tmp, &csi->csi_chans, list) {
0633 if (chan->mipi)
0634 tegra_mipi_free(chan->mipi);
0635
0636 subdev = &chan->subdev;
0637 if (subdev->dev) {
0638 if (!IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
0639 v4l2_async_unregister_subdev(subdev);
0640 media_entity_cleanup(&subdev->entity);
0641 }
0642
0643 list_del(&chan->list);
0644 kfree(chan);
0645 }
0646 }
0647
0648 static int __maybe_unused csi_runtime_suspend(struct device *dev)
0649 {
0650 struct tegra_csi *csi = dev_get_drvdata(dev);
0651
0652 clk_bulk_disable_unprepare(csi->soc->num_clks, csi->clks);
0653
0654 return 0;
0655 }
0656
0657 static int __maybe_unused csi_runtime_resume(struct device *dev)
0658 {
0659 struct tegra_csi *csi = dev_get_drvdata(dev);
0660 int ret;
0661
0662 ret = clk_bulk_prepare_enable(csi->soc->num_clks, csi->clks);
0663 if (ret < 0) {
0664 dev_err(csi->dev, "failed to enable clocks: %d\n", ret);
0665 return ret;
0666 }
0667
0668 return 0;
0669 }
0670
0671 static int tegra_csi_init(struct host1x_client *client)
0672 {
0673 struct tegra_csi *csi = host1x_client_to_csi(client);
0674 struct tegra_video_device *vid = dev_get_drvdata(client->host);
0675 int ret;
0676
0677 INIT_LIST_HEAD(&csi->csi_chans);
0678
0679 if (IS_ENABLED(CONFIG_VIDEO_TEGRA_TPG))
0680 ret = tegra_csi_tpg_channels_alloc(csi);
0681 else
0682 ret = tegra_csi_channels_alloc(csi);
0683 if (ret < 0) {
0684 dev_err(csi->dev,
0685 "failed to allocate channels: %d\n", ret);
0686 goto cleanup;
0687 }
0688
0689 ret = tegra_csi_channels_init(csi);
0690 if (ret < 0)
0691 goto cleanup;
0692
0693 vid->csi = csi;
0694
0695 return 0;
0696
0697 cleanup:
0698 tegra_csi_channels_cleanup(csi);
0699 return ret;
0700 }
0701
0702 static int tegra_csi_exit(struct host1x_client *client)
0703 {
0704 struct tegra_csi *csi = host1x_client_to_csi(client);
0705
0706 tegra_csi_channels_cleanup(csi);
0707
0708 return 0;
0709 }
0710
0711 static const struct host1x_client_ops csi_client_ops = {
0712 .init = tegra_csi_init,
0713 .exit = tegra_csi_exit,
0714 };
0715
0716 static int tegra_csi_probe(struct platform_device *pdev)
0717 {
0718 struct tegra_csi *csi;
0719 unsigned int i;
0720 int ret;
0721
0722 csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL);
0723 if (!csi)
0724 return -ENOMEM;
0725
0726 csi->iomem = devm_platform_ioremap_resource(pdev, 0);
0727 if (IS_ERR(csi->iomem))
0728 return PTR_ERR(csi->iomem);
0729
0730 csi->soc = of_device_get_match_data(&pdev->dev);
0731
0732 csi->clks = devm_kcalloc(&pdev->dev, csi->soc->num_clks,
0733 sizeof(*csi->clks), GFP_KERNEL);
0734 if (!csi->clks)
0735 return -ENOMEM;
0736
0737 for (i = 0; i < csi->soc->num_clks; i++)
0738 csi->clks[i].id = csi->soc->clk_names[i];
0739
0740 ret = devm_clk_bulk_get(&pdev->dev, csi->soc->num_clks, csi->clks);
0741 if (ret) {
0742 dev_err(&pdev->dev, "failed to get the clocks: %d\n", ret);
0743 return ret;
0744 }
0745
0746 if (!pdev->dev.pm_domain) {
0747 ret = -ENOENT;
0748 dev_warn(&pdev->dev, "PM domain is not attached: %d\n", ret);
0749 return ret;
0750 }
0751
0752 csi->dev = &pdev->dev;
0753 csi->ops = csi->soc->ops;
0754 platform_set_drvdata(pdev, csi);
0755 pm_runtime_enable(&pdev->dev);
0756
0757
0758 INIT_LIST_HEAD(&csi->client.list);
0759 csi->client.ops = &csi_client_ops;
0760 csi->client.dev = &pdev->dev;
0761
0762 ret = host1x_client_register(&csi->client);
0763 if (ret < 0) {
0764 dev_err(&pdev->dev,
0765 "failed to register host1x client: %d\n", ret);
0766 goto rpm_disable;
0767 }
0768
0769 return 0;
0770
0771 rpm_disable:
0772 pm_runtime_disable(&pdev->dev);
0773 return ret;
0774 }
0775
0776 static int tegra_csi_remove(struct platform_device *pdev)
0777 {
0778 struct tegra_csi *csi = platform_get_drvdata(pdev);
0779 int err;
0780
0781 err = host1x_client_unregister(&csi->client);
0782 if (err < 0) {
0783 dev_err(&pdev->dev,
0784 "failed to unregister host1x client: %d\n", err);
0785 return err;
0786 }
0787
0788 pm_runtime_disable(&pdev->dev);
0789
0790 return 0;
0791 }
0792
0793 static const struct of_device_id tegra_csi_of_id_table[] = {
0794 #if defined(CONFIG_ARCH_TEGRA_210_SOC)
0795 { .compatible = "nvidia,tegra210-csi", .data = &tegra210_csi_soc },
0796 #endif
0797 { }
0798 };
0799 MODULE_DEVICE_TABLE(of, tegra_csi_of_id_table);
0800
0801 static const struct dev_pm_ops tegra_csi_pm_ops = {
0802 SET_RUNTIME_PM_OPS(csi_runtime_suspend, csi_runtime_resume, NULL)
0803 };
0804
0805 struct platform_driver tegra_csi_driver = {
0806 .driver = {
0807 .name = "tegra-csi",
0808 .of_match_table = tegra_csi_of_id_table,
0809 .pm = &tegra_csi_pm_ops,
0810 },
0811 .probe = tegra_csi_probe,
0812 .remove = tegra_csi_remove,
0813 };