2514 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * camss.c4 *5 * Qualcomm MSM Camera Subsystem - Core6 *7 * Copyright (c) 2015, The Linux Foundation. All rights reserved.8 * Copyright (C) 2015-2018 Linaro Ltd.9 */10#include <linux/clk.h>11#include <linux/interconnect.h>12#include <linux/media-bus-format.h>13#include <linux/media.h>14#include <linux/module.h>15#include <linux/platform_device.h>16#include <linux/of.h>17#include <linux/of_device.h>18#include <linux/of_graph.h>19#include <linux/pm_runtime.h>20#include <linux/pm_domain.h>21#include <linux/slab.h>22#include <linux/videodev2.h>23 24#include <media/media-device.h>25#include <media/v4l2-async.h>26#include <media/v4l2-device.h>27#include <media/v4l2-mc.h>28#include <media/v4l2-fwnode.h>29 30#include "camss.h"31 32#define CAMSS_CLOCK_MARGIN_NUMERATOR 10533#define CAMSS_CLOCK_MARGIN_DENOMINATOR 10034 35static const struct parent_dev_ops vfe_parent_dev_ops;36 37static const struct camss_subdev_resources csiphy_res_8x16[] = {38 /* CSIPHY0 */39 {40 .regulators = {},41 .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer" },42 .clock_rate = { { 0 },43 { 0 },44 { 0 },45 { 100000000, 200000000 } },46 .reg = { "csiphy0", "csiphy0_clk_mux" },47 .interrupt = { "csiphy0" },48 .csiphy = {49 .hw_ops = &csiphy_ops_2ph_1_0,50 .formats = &csiphy_formats_8x1651 }52 },53 54 /* CSIPHY1 */55 {56 .regulators = {},57 .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer" },58 .clock_rate = { { 0 },59 { 0 },60 { 0 },61 { 100000000, 200000000 } },62 .reg = { "csiphy1", "csiphy1_clk_mux" },63 .interrupt = { "csiphy1" },64 .csiphy = {65 .hw_ops = &csiphy_ops_2ph_1_0,66 .formats = &csiphy_formats_8x1667 }68 }69};70 71static const struct camss_subdev_resources csid_res_8x16[] = {72 /* CSID0 */73 {74 .regulators = { "vdda" },75 .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb",76 "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" },77 .clock_rate = { { 0 },78 { 0 },79 { 0 },80 { 0 },81 { 100000000, 200000000 },82 { 0 },83 { 0 },84 { 0 } },85 .reg = { "csid0" },86 .interrupt = { "csid0" },87 .csid = {88 .hw_ops = &csid_ops_4_1,89 .parent_dev_ops = &vfe_parent_dev_ops,90 .formats = &csid_formats_4_191 }92 },93 94 /* CSID1 */95 {96 .regulators = { "vdda" },97 .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb",98 "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" },99 .clock_rate = { { 0 },100 { 0 },101 { 0 },102 { 0 },103 { 100000000, 200000000 },104 { 0 },105 { 0 },106 { 0 } },107 .reg = { "csid1" },108 .interrupt = { "csid1" },109 .csid = {110 .hw_ops = &csid_ops_4_1,111 .parent_dev_ops = &vfe_parent_dev_ops,112 .formats = &csid_formats_4_1113 }114 },115};116 117static const struct camss_subdev_resources ispif_res_8x16 = {118 /* ISPIF */119 .clock = { "top_ahb", "ahb", "ispif_ahb",120 "csi0", "csi0_pix", "csi0_rdi",121 "csi1", "csi1_pix", "csi1_rdi" },122 .clock_for_reset = { "vfe0", "csi_vfe0" },123 .reg = { "ispif", "csi_clk_mux" },124 .interrupt = { "ispif" },125};126 127static const struct camss_subdev_resources vfe_res_8x16[] = {128 /* VFE0 */129 {130 .regulators = {},131 .clock = { "top_ahb", "vfe0", "csi_vfe0",132 "vfe_ahb", "vfe_axi", "ahb" },133 .clock_rate = { { 0 },134 { 50000000, 80000000, 100000000, 160000000,135 177780000, 200000000, 266670000, 320000000,136 400000000, 465000000 },137 { 0 },138 { 0 },139 { 0 },140 { 0 },141 { 0 },142 { 0 },143 { 0 } },144 .reg = { "vfe0" },145 .interrupt = { "vfe0" },146 .vfe = {147 .line_num = 3,148 .hw_ops = &vfe_ops_4_1,149 .formats_rdi = &vfe_formats_rdi_8x16,150 .formats_pix = &vfe_formats_pix_8x16151 }152 }153};154 155static const struct camss_subdev_resources csiphy_res_8x96[] = {156 /* CSIPHY0 */157 {158 .regulators = {},159 .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer" },160 .clock_rate = { { 0 },161 { 0 },162 { 0 },163 { 100000000, 200000000, 266666667 } },164 .reg = { "csiphy0", "csiphy0_clk_mux" },165 .interrupt = { "csiphy0" },166 .csiphy = {167 .hw_ops = &csiphy_ops_3ph_1_0,168 .formats = &csiphy_formats_8x96169 }170 },171 172 /* CSIPHY1 */173 {174 .regulators = {},175 .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer" },176 .clock_rate = { { 0 },177 { 0 },178 { 0 },179 { 100000000, 200000000, 266666667 } },180 .reg = { "csiphy1", "csiphy1_clk_mux" },181 .interrupt = { "csiphy1" },182 .csiphy = {183 .hw_ops = &csiphy_ops_3ph_1_0,184 .formats = &csiphy_formats_8x96185 }186 },187 188 /* CSIPHY2 */189 {190 .regulators = {},191 .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy2_timer" },192 .clock_rate = { { 0 },193 { 0 },194 { 0 },195 { 100000000, 200000000, 266666667 } },196 .reg = { "csiphy2", "csiphy2_clk_mux" },197 .interrupt = { "csiphy2" },198 .csiphy = {199 .hw_ops = &csiphy_ops_3ph_1_0,200 .formats = &csiphy_formats_8x96201 }202 }203};204 205static const struct camss_subdev_resources csid_res_8x96[] = {206 /* CSID0 */207 {208 .regulators = { "vdda" },209 .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb",210 "csi0", "csi0_phy", "csi0_pix", "csi0_rdi" },211 .clock_rate = { { 0 },212 { 0 },213 { 0 },214 { 0 },215 { 100000000, 200000000, 266666667 },216 { 0 },217 { 0 },218 { 0 } },219 .reg = { "csid0" },220 .interrupt = { "csid0" },221 .csid = {222 .hw_ops = &csid_ops_4_7,223 .parent_dev_ops = &vfe_parent_dev_ops,224 .formats = &csid_formats_4_7225 }226 },227 228 /* CSID1 */229 {230 .regulators = { "vdda" },231 .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb",232 "csi1", "csi1_phy", "csi1_pix", "csi1_rdi" },233 .clock_rate = { { 0 },234 { 0 },235 { 0 },236 { 0 },237 { 100000000, 200000000, 266666667 },238 { 0 },239 { 0 },240 { 0 } },241 .reg = { "csid1" },242 .interrupt = { "csid1" },243 .csid = {244 .hw_ops = &csid_ops_4_7,245 .parent_dev_ops = &vfe_parent_dev_ops,246 .formats = &csid_formats_4_7247 }248 },249 250 /* CSID2 */251 {252 .regulators = { "vdda" },253 .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb",254 "csi2", "csi2_phy", "csi2_pix", "csi2_rdi" },255 .clock_rate = { { 0 },256 { 0 },257 { 0 },258 { 0 },259 { 100000000, 200000000, 266666667 },260 { 0 },261 { 0 },262 { 0 } },263 .reg = { "csid2" },264 .interrupt = { "csid2" },265 .csid = {266 .hw_ops = &csid_ops_4_7,267 .parent_dev_ops = &vfe_parent_dev_ops,268 .formats = &csid_formats_4_7269 }270 },271 272 /* CSID3 */273 {274 .regulators = { "vdda" },275 .clock = { "top_ahb", "ispif_ahb", "csi3_ahb", "ahb",276 "csi3", "csi3_phy", "csi3_pix", "csi3_rdi" },277 .clock_rate = { { 0 },278 { 0 },279 { 0 },280 { 0 },281 { 100000000, 200000000, 266666667 },282 { 0 },283 { 0 },284 { 0 } },285 .reg = { "csid3" },286 .interrupt = { "csid3" },287 .csid = {288 .hw_ops = &csid_ops_4_7,289 .parent_dev_ops = &vfe_parent_dev_ops,290 .formats = &csid_formats_4_7291 }292 }293};294 295static const struct camss_subdev_resources ispif_res_8x96 = {296 /* ISPIF */297 .clock = { "top_ahb", "ahb", "ispif_ahb",298 "csi0", "csi0_pix", "csi0_rdi",299 "csi1", "csi1_pix", "csi1_rdi",300 "csi2", "csi2_pix", "csi2_rdi",301 "csi3", "csi3_pix", "csi3_rdi" },302 .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" },303 .reg = { "ispif", "csi_clk_mux" },304 .interrupt = { "ispif" },305};306 307static const struct camss_subdev_resources vfe_res_8x96[] = {308 /* VFE0 */309 {310 .regulators = {},311 .clock = { "top_ahb", "ahb", "vfe0", "csi_vfe0", "vfe_ahb",312 "vfe0_ahb", "vfe_axi", "vfe0_stream"},313 .clock_rate = { { 0 },314 { 0 },315 { 75000000, 100000000, 300000000,316 320000000, 480000000, 600000000 },317 { 0 },318 { 0 },319 { 0 },320 { 0 },321 { 0 } },322 .reg = { "vfe0" },323 .interrupt = { "vfe0" },324 .vfe = {325 .line_num = 3,326 .has_pd = true,327 .hw_ops = &vfe_ops_4_7,328 .formats_rdi = &vfe_formats_rdi_8x96,329 .formats_pix = &vfe_formats_pix_8x96330 }331 },332 333 /* VFE1 */334 {335 .regulators = {},336 .clock = { "top_ahb", "ahb", "vfe1", "csi_vfe1", "vfe_ahb",337 "vfe1_ahb", "vfe_axi", "vfe1_stream"},338 .clock_rate = { { 0 },339 { 0 },340 { 75000000, 100000000, 300000000,341 320000000, 480000000, 600000000 },342 { 0 },343 { 0 },344 { 0 },345 { 0 },346 { 0 } },347 .reg = { "vfe1" },348 .interrupt = { "vfe1" },349 .vfe = {350 .line_num = 3,351 .has_pd = true,352 .hw_ops = &vfe_ops_4_7,353 .formats_rdi = &vfe_formats_rdi_8x96,354 .formats_pix = &vfe_formats_pix_8x96355 }356 }357};358 359static const struct camss_subdev_resources csiphy_res_660[] = {360 /* CSIPHY0 */361 {362 .regulators = {},363 .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy0_timer",364 "csi0_phy", "csiphy_ahb2crif" },365 .clock_rate = { { 0 },366 { 0 },367 { 0 },368 { 100000000, 200000000, 269333333 },369 { 0 } },370 .reg = { "csiphy0", "csiphy0_clk_mux" },371 .interrupt = { "csiphy0" },372 .csiphy = {373 .hw_ops = &csiphy_ops_3ph_1_0,374 .formats = &csiphy_formats_8x96375 }376 },377 378 /* CSIPHY1 */379 {380 .regulators = {},381 .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy1_timer",382 "csi1_phy", "csiphy_ahb2crif" },383 .clock_rate = { { 0 },384 { 0 },385 { 0 },386 { 100000000, 200000000, 269333333 },387 { 0 } },388 .reg = { "csiphy1", "csiphy1_clk_mux" },389 .interrupt = { "csiphy1" },390 .csiphy = {391 .hw_ops = &csiphy_ops_3ph_1_0,392 .formats = &csiphy_formats_8x96393 }394 },395 396 /* CSIPHY2 */397 {398 .regulators = {},399 .clock = { "top_ahb", "ispif_ahb", "ahb", "csiphy2_timer",400 "csi2_phy", "csiphy_ahb2crif" },401 .clock_rate = { { 0 },402 { 0 },403 { 0 },404 { 100000000, 200000000, 269333333 },405 { 0 } },406 .reg = { "csiphy2", "csiphy2_clk_mux" },407 .interrupt = { "csiphy2" },408 .csiphy = {409 .hw_ops = &csiphy_ops_3ph_1_0,410 .formats = &csiphy_formats_8x96411 }412 }413};414 415static const struct camss_subdev_resources csid_res_660[] = {416 /* CSID0 */417 {418 .regulators = { "vdda", "vdd_sec" },419 .clock = { "top_ahb", "ispif_ahb", "csi0_ahb", "ahb",420 "csi0", "csi0_phy", "csi0_pix", "csi0_rdi",421 "cphy_csid0" },422 .clock_rate = { { 0 },423 { 0 },424 { 0 },425 { 0 },426 { 100000000, 200000000, 310000000,427 404000000, 465000000 },428 { 0 },429 { 0 },430 { 0 },431 { 0 } },432 .reg = { "csid0" },433 .interrupt = { "csid0" },434 .csid = {435 .hw_ops = &csid_ops_4_7,436 .parent_dev_ops = &vfe_parent_dev_ops,437 .formats = &csid_formats_4_7438 }439 },440 441 /* CSID1 */442 {443 .regulators = { "vdda", "vdd_sec" },444 .clock = { "top_ahb", "ispif_ahb", "csi1_ahb", "ahb",445 "csi1", "csi1_phy", "csi1_pix", "csi1_rdi",446 "cphy_csid1" },447 .clock_rate = { { 0 },448 { 0 },449 { 0 },450 { 0 },451 { 100000000, 200000000, 310000000,452 404000000, 465000000 },453 { 0 },454 { 0 },455 { 0 },456 { 0 } },457 .reg = { "csid1" },458 .interrupt = { "csid1" },459 .csid = {460 .hw_ops = &csid_ops_4_7,461 .parent_dev_ops = &vfe_parent_dev_ops,462 .formats = &csid_formats_4_7463 }464 },465 466 /* CSID2 */467 {468 .regulators = { "vdda", "vdd_sec" },469 .clock = { "top_ahb", "ispif_ahb", "csi2_ahb", "ahb",470 "csi2", "csi2_phy", "csi2_pix", "csi2_rdi",471 "cphy_csid2" },472 .clock_rate = { { 0 },473 { 0 },474 { 0 },475 { 0 },476 { 100000000, 200000000, 310000000,477 404000000, 465000000 },478 { 0 },479 { 0 },480 { 0 },481 { 0 } },482 .reg = { "csid2" },483 .interrupt = { "csid2" },484 .csid = {485 .hw_ops = &csid_ops_4_7,486 .parent_dev_ops = &vfe_parent_dev_ops,487 .formats = &csid_formats_4_7488 }489 },490 491 /* CSID3 */492 {493 .regulators = { "vdda", "vdd_sec" },494 .clock = { "top_ahb", "ispif_ahb", "csi3_ahb", "ahb",495 "csi3", "csi3_phy", "csi3_pix", "csi3_rdi",496 "cphy_csid3" },497 .clock_rate = { { 0 },498 { 0 },499 { 0 },500 { 0 },501 { 100000000, 200000000, 310000000,502 404000000, 465000000 },503 { 0 },504 { 0 },505 { 0 },506 { 0 } },507 .reg = { "csid3" },508 .interrupt = { "csid3" },509 .csid = {510 .hw_ops = &csid_ops_4_7,511 .parent_dev_ops = &vfe_parent_dev_ops,512 .formats = &csid_formats_4_7513 }514 }515};516 517static const struct camss_subdev_resources ispif_res_660 = {518 /* ISPIF */519 .clock = { "top_ahb", "ahb", "ispif_ahb",520 "csi0", "csi0_pix", "csi0_rdi",521 "csi1", "csi1_pix", "csi1_rdi",522 "csi2", "csi2_pix", "csi2_rdi",523 "csi3", "csi3_pix", "csi3_rdi" },524 .clock_for_reset = { "vfe0", "csi_vfe0", "vfe1", "csi_vfe1" },525 .reg = { "ispif", "csi_clk_mux" },526 .interrupt = { "ispif" },527};528 529static const struct camss_subdev_resources vfe_res_660[] = {530 /* VFE0 */531 {532 .regulators = {},533 .clock = { "throttle_axi", "top_ahb", "ahb", "vfe0",534 "csi_vfe0", "vfe_ahb", "vfe0_ahb", "vfe_axi",535 "vfe0_stream"},536 .clock_rate = { { 0 },537 { 0 },538 { 0 },539 { 120000000, 200000000, 256000000,540 300000000, 404000000, 480000000,541 540000000, 576000000 },542 { 0 },543 { 0 },544 { 0 },545 { 0 },546 { 0 } },547 .reg = { "vfe0" },548 .interrupt = { "vfe0" },549 .vfe = {550 .line_num = 3,551 .has_pd = true,552 .hw_ops = &vfe_ops_4_8,553 .formats_rdi = &vfe_formats_rdi_8x96,554 .formats_pix = &vfe_formats_pix_8x96555 }556 },557 558 /* VFE1 */559 {560 .regulators = {},561 .clock = { "throttle_axi", "top_ahb", "ahb", "vfe1",562 "csi_vfe1", "vfe_ahb", "vfe1_ahb", "vfe_axi",563 "vfe1_stream"},564 .clock_rate = { { 0 },565 { 0 },566 { 0 },567 { 120000000, 200000000, 256000000,568 300000000, 404000000, 480000000,569 540000000, 576000000 },570 { 0 },571 { 0 },572 { 0 },573 { 0 },574 { 0 } },575 .reg = { "vfe1" },576 .interrupt = { "vfe1" },577 .vfe = {578 .line_num = 3,579 .has_pd = true,580 .hw_ops = &vfe_ops_4_8,581 .formats_rdi = &vfe_formats_rdi_8x96,582 .formats_pix = &vfe_formats_pix_8x96583 }584 }585};586 587static const struct camss_subdev_resources csiphy_res_845[] = {588 /* CSIPHY0 */589 {590 .regulators = {},591 .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src",592 "cpas_ahb", "cphy_rx_src", "csiphy0",593 "csiphy0_timer_src", "csiphy0_timer" },594 .clock_rate = { { 0 },595 { 0 },596 { 0 },597 { 0 },598 { 0 },599 { 0 },600 { 0 },601 { 19200000, 240000000, 269333333 } },602 .reg = { "csiphy0" },603 .interrupt = { "csiphy0" },604 .csiphy = {605 .hw_ops = &csiphy_ops_3ph_1_0,606 .formats = &csiphy_formats_sdm845607 }608 },609 610 /* CSIPHY1 */611 {612 .regulators = {},613 .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src",614 "cpas_ahb", "cphy_rx_src", "csiphy1",615 "csiphy1_timer_src", "csiphy1_timer" },616 .clock_rate = { { 0 },617 { 0 },618 { 0 },619 { 0 },620 { 0 },621 { 0 },622 { 0 },623 { 19200000, 240000000, 269333333 } },624 .reg = { "csiphy1" },625 .interrupt = { "csiphy1" },626 .csiphy = {627 .hw_ops = &csiphy_ops_3ph_1_0,628 .formats = &csiphy_formats_sdm845629 }630 },631 632 /* CSIPHY2 */633 {634 .regulators = {},635 .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src",636 "cpas_ahb", "cphy_rx_src", "csiphy2",637 "csiphy2_timer_src", "csiphy2_timer" },638 .clock_rate = { { 0 },639 { 0 },640 { 0 },641 { 0 },642 { 0 },643 { 0 },644 { 0 },645 { 19200000, 240000000, 269333333 } },646 .reg = { "csiphy2" },647 .interrupt = { "csiphy2" },648 .csiphy = {649 .hw_ops = &csiphy_ops_3ph_1_0,650 .formats = &csiphy_formats_sdm845651 }652 },653 654 /* CSIPHY3 */655 {656 .regulators = {},657 .clock = { "camnoc_axi", "soc_ahb", "slow_ahb_src",658 "cpas_ahb", "cphy_rx_src", "csiphy3",659 "csiphy3_timer_src", "csiphy3_timer" },660 .clock_rate = { { 0 },661 { 0 },662 { 0 },663 { 0 },664 { 0 },665 { 0 },666 { 0 },667 { 19200000, 240000000, 269333333 } },668 .reg = { "csiphy3" },669 .interrupt = { "csiphy3" },670 .csiphy = {671 .hw_ops = &csiphy_ops_3ph_1_0,672 .formats = &csiphy_formats_sdm845673 }674 }675};676 677static const struct camss_subdev_resources csid_res_845[] = {678 /* CSID0 */679 {680 .regulators = { "vdda-phy", "vdda-pll" },681 .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src",682 "soc_ahb", "vfe0", "vfe0_src",683 "vfe0_cphy_rx", "csi0",684 "csi0_src" },685 .clock_rate = { { 0 },686 { 384000000 },687 { 80000000 },688 { 0 },689 { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 },690 { 320000000 },691 { 0 },692 { 19200000, 75000000, 384000000, 538666667 },693 { 384000000 } },694 .reg = { "csid0" },695 .interrupt = { "csid0" },696 .csid = {697 .hw_ops = &csid_ops_gen2,698 .parent_dev_ops = &vfe_parent_dev_ops,699 .formats = &csid_formats_gen2700 }701 },702 703 /* CSID1 */704 {705 .regulators = { "vdda-phy", "vdda-pll" },706 .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src",707 "soc_ahb", "vfe1", "vfe1_src",708 "vfe1_cphy_rx", "csi1",709 "csi1_src" },710 .clock_rate = { { 0 },711 { 384000000 },712 { 80000000 },713 { 0 },714 { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 },715 { 320000000 },716 { 0 },717 { 19200000, 75000000, 384000000, 538666667 },718 { 384000000 } },719 .reg = { "csid1" },720 .interrupt = { "csid1" },721 .csid = {722 .hw_ops = &csid_ops_gen2,723 .parent_dev_ops = &vfe_parent_dev_ops,724 .formats = &csid_formats_gen2725 }726 },727 728 /* CSID2 */729 {730 .regulators = { "vdda-phy", "vdda-pll" },731 .clock = { "cpas_ahb", "cphy_rx_src", "slow_ahb_src",732 "soc_ahb", "vfe_lite", "vfe_lite_src",733 "vfe_lite_cphy_rx", "csi2",734 "csi2_src" },735 .clock_rate = { { 0 },736 { 384000000 },737 { 80000000 },738 { 0 },739 { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 },740 { 320000000 },741 { 0 },742 { 19200000, 75000000, 384000000, 538666667 },743 { 384000000 } },744 .reg = { "csid2" },745 .interrupt = { "csid2" },746 .csid = {747 .is_lite = true,748 .hw_ops = &csid_ops_gen2,749 .parent_dev_ops = &vfe_parent_dev_ops,750 .formats = &csid_formats_gen2751 }752 }753};754 755static const struct camss_subdev_resources vfe_res_845[] = {756 /* VFE0 */757 {758 .regulators = {},759 .clock = { "camnoc_axi", "cpas_ahb", "slow_ahb_src",760 "soc_ahb", "vfe0", "vfe0_axi",761 "vfe0_src", "csi0",762 "csi0_src"},763 .clock_rate = { { 0 },764 { 0 },765 { 80000000 },766 { 0 },767 { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 },768 { 0 },769 { 320000000 },770 { 19200000, 75000000, 384000000, 538666667 },771 { 384000000 } },772 .reg = { "vfe0" },773 .interrupt = { "vfe0" },774 .vfe = {775 .line_num = 4,776 .has_pd = true,777 .hw_ops = &vfe_ops_170,778 .formats_rdi = &vfe_formats_rdi_845,779 .formats_pix = &vfe_formats_pix_845780 }781 },782 783 /* VFE1 */784 {785 .regulators = {},786 .clock = { "camnoc_axi", "cpas_ahb", "slow_ahb_src",787 "soc_ahb", "vfe1", "vfe1_axi",788 "vfe1_src", "csi1",789 "csi1_src"},790 .clock_rate = { { 0 },791 { 0 },792 { 80000000 },793 { 0 },794 { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 },795 { 0 },796 { 320000000 },797 { 19200000, 75000000, 384000000, 538666667 },798 { 384000000 } },799 .reg = { "vfe1" },800 .interrupt = { "vfe1" },801 .vfe = {802 .line_num = 4,803 .has_pd = true,804 .hw_ops = &vfe_ops_170,805 .formats_rdi = &vfe_formats_rdi_845,806 .formats_pix = &vfe_formats_pix_845807 }808 },809 810 /* VFE-lite */811 {812 .regulators = {},813 .clock = { "camnoc_axi", "cpas_ahb", "slow_ahb_src",814 "soc_ahb", "vfe_lite",815 "vfe_lite_src", "csi2",816 "csi2_src"},817 .clock_rate = { { 0 },818 { 0 },819 { 80000000 },820 { 0 },821 { 19200000, 100000000, 320000000, 404000000, 480000000, 600000000 },822 { 320000000 },823 { 19200000, 75000000, 384000000, 538666667 },824 { 384000000 } },825 .reg = { "vfe_lite" },826 .interrupt = { "vfe_lite" },827 .vfe = {828 .is_lite = true,829 .line_num = 4,830 .hw_ops = &vfe_ops_170,831 .formats_rdi = &vfe_formats_rdi_845,832 .formats_pix = &vfe_formats_pix_845833 }834 }835};836 837static const struct camss_subdev_resources csiphy_res_8250[] = {838 /* CSIPHY0 */839 {840 .regulators = {},841 .clock = { "csiphy0", "csiphy0_timer" },842 .clock_rate = { { 400000000 },843 { 300000000 } },844 .reg = { "csiphy0" },845 .interrupt = { "csiphy0" },846 .csiphy = {847 .hw_ops = &csiphy_ops_3ph_1_0,848 .formats = &csiphy_formats_sdm845849 }850 },851 /* CSIPHY1 */852 {853 .regulators = {},854 .clock = { "csiphy1", "csiphy1_timer" },855 .clock_rate = { { 400000000 },856 { 300000000 } },857 .reg = { "csiphy1" },858 .interrupt = { "csiphy1" },859 .csiphy = {860 .hw_ops = &csiphy_ops_3ph_1_0,861 .formats = &csiphy_formats_sdm845862 }863 },864 /* CSIPHY2 */865 {866 .regulators = {},867 .clock = { "csiphy2", "csiphy2_timer" },868 .clock_rate = { { 400000000 },869 { 300000000 } },870 .reg = { "csiphy2" },871 .interrupt = { "csiphy2" },872 .csiphy = {873 .hw_ops = &csiphy_ops_3ph_1_0,874 .formats = &csiphy_formats_sdm845875 }876 },877 /* CSIPHY3 */878 {879 .regulators = {},880 .clock = { "csiphy3", "csiphy3_timer" },881 .clock_rate = { { 400000000 },882 { 300000000 } },883 .reg = { "csiphy3" },884 .interrupt = { "csiphy3" },885 .csiphy = {886 .hw_ops = &csiphy_ops_3ph_1_0,887 .formats = &csiphy_formats_sdm845888 }889 },890 /* CSIPHY4 */891 {892 .regulators = {},893 .clock = { "csiphy4", "csiphy4_timer" },894 .clock_rate = { { 400000000 },895 { 300000000 } },896 .reg = { "csiphy4" },897 .interrupt = { "csiphy4" },898 .csiphy = {899 .hw_ops = &csiphy_ops_3ph_1_0,900 .formats = &csiphy_formats_sdm845901 }902 },903 /* CSIPHY5 */904 {905 .regulators = {},906 .clock = { "csiphy5", "csiphy5_timer" },907 .clock_rate = { { 400000000 },908 { 300000000 } },909 .reg = { "csiphy5" },910 .interrupt = { "csiphy5" },911 .csiphy = {912 .hw_ops = &csiphy_ops_3ph_1_0,913 .formats = &csiphy_formats_sdm845914 }915 }916};917 918static const struct camss_subdev_resources csid_res_8250[] = {919 /* CSID0 */920 {921 .regulators = { "vdda-phy", "vdda-pll" },922 .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0", "vfe0_areg", "vfe0_ahb" },923 .clock_rate = { { 400000000 },924 { 400000000 },925 { 350000000, 475000000, 576000000, 720000000 },926 { 100000000, 200000000, 300000000, 400000000 },927 { 0 } },928 .reg = { "csid0" },929 .interrupt = { "csid0" },930 .csid = {931 .hw_ops = &csid_ops_gen2,932 .parent_dev_ops = &vfe_parent_dev_ops,933 .formats = &csid_formats_gen2934 }935 },936 /* CSID1 */937 {938 .regulators = { "vdda-phy", "vdda-pll" },939 .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1", "vfe1_areg", "vfe1_ahb" },940 .clock_rate = { { 400000000 },941 { 400000000 },942 { 350000000, 475000000, 576000000, 720000000 },943 { 100000000, 200000000, 300000000, 400000000 },944 { 0 } },945 .reg = { "csid1" },946 .interrupt = { "csid1" },947 .csid = {948 .hw_ops = &csid_ops_gen2,949 .parent_dev_ops = &vfe_parent_dev_ops,950 .formats = &csid_formats_gen2951 }952 },953 /* CSID2 */954 {955 .regulators = { "vdda-phy", "vdda-pll" },956 .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" },957 .clock_rate = { { 400000000 },958 { 400000000 },959 { 400000000, 480000000 },960 { 0 } },961 .reg = { "csid2" },962 .interrupt = { "csid2" },963 .csid = {964 .is_lite = true,965 .hw_ops = &csid_ops_gen2,966 .parent_dev_ops = &vfe_parent_dev_ops,967 .formats = &csid_formats_gen2968 }969 },970 /* CSID3 */971 {972 .regulators = { "vdda-phy", "vdda-pll" },973 .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "vfe_lite", "vfe_lite_ahb" },974 .clock_rate = { { 400000000 },975 { 400000000 },976 { 400000000, 480000000 },977 { 0 } },978 .reg = { "csid3" },979 .interrupt = { "csid3" },980 .csid = {981 .is_lite = true,982 .hw_ops = &csid_ops_gen2,983 .parent_dev_ops = &vfe_parent_dev_ops,984 .formats = &csid_formats_gen2985 }986 }987};988 989static const struct camss_subdev_resources vfe_res_8250[] = {990 /* VFE0 */991 {992 .regulators = {},993 .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb",994 "camnoc_axi", "vfe0_ahb", "vfe0_areg", "vfe0",995 "vfe0_axi", "cam_hf_axi" },996 .clock_rate = { { 19200000, 300000000, 400000000, 480000000 },997 { 19200000, 80000000 },998 { 19200000 },999 { 0 },1000 { 0 },1001 { 100000000, 200000000, 300000000, 400000000 },1002 { 350000000, 475000000, 576000000, 720000000 },1003 { 0 },1004 { 0 } },1005 .reg = { "vfe0" },1006 .interrupt = { "vfe0" },1007 .vfe = {1008 .line_num = 3,1009 .has_pd = true,1010 .pd_name = "ife0",1011 .hw_ops = &vfe_ops_480,1012 .formats_rdi = &vfe_formats_rdi_845,1013 .formats_pix = &vfe_formats_pix_8451014 }1015 },1016 /* VFE1 */1017 {1018 .regulators = {},1019 .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb",1020 "camnoc_axi", "vfe1_ahb", "vfe1_areg", "vfe1",1021 "vfe1_axi", "cam_hf_axi" },1022 .clock_rate = { { 19200000, 300000000, 400000000, 480000000 },1023 { 19200000, 80000000 },1024 { 19200000 },1025 { 0 },1026 { 0 },1027 { 100000000, 200000000, 300000000, 400000000 },1028 { 350000000, 475000000, 576000000, 720000000 },1029 { 0 },1030 { 0 } },1031 .reg = { "vfe1" },1032 .interrupt = { "vfe1" },1033 .vfe = {1034 .line_num = 3,1035 .has_pd = true,1036 .pd_name = "ife1",1037 .hw_ops = &vfe_ops_480,1038 .formats_rdi = &vfe_formats_rdi_845,1039 .formats_pix = &vfe_formats_pix_8451040 }1041 },1042 /* VFE2 (lite) */1043 {1044 .regulators = {},1045 .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb",1046 "camnoc_axi", "vfe_lite_ahb", "vfe_lite_axi",1047 "vfe_lite", "cam_hf_axi" },1048 .clock_rate = { { 19200000, 300000000, 400000000, 480000000 },1049 { 19200000, 80000000 },1050 { 19200000 },1051 { 0 },1052 { 0 },1053 { 0 },1054 { 400000000, 480000000 },1055 { 0 } },1056 .reg = { "vfe_lite0" },1057 .interrupt = { "vfe_lite0" },1058 .vfe = {1059 .is_lite = true,1060 .line_num = 4,1061 .hw_ops = &vfe_ops_480,1062 .formats_rdi = &vfe_formats_rdi_845,1063 .formats_pix = &vfe_formats_pix_8451064 }1065 },1066 /* VFE3 (lite) */1067 {1068 .regulators = {},1069 .clock = { "camnoc_axi_src", "slow_ahb_src", "cpas_ahb",1070 "camnoc_axi", "vfe_lite_ahb", "vfe_lite_axi",1071 "vfe_lite", "cam_hf_axi" },1072 .clock_rate = { { 19200000, 300000000, 400000000, 480000000 },1073 { 19200000, 80000000 },1074 { 19200000 },1075 { 0 },1076 { 0 },1077 { 0 },1078 { 400000000, 480000000 },1079 { 0 } },1080 .reg = { "vfe_lite1" },1081 .interrupt = { "vfe_lite1" },1082 .vfe = {1083 .is_lite = true,1084 .line_num = 4,1085 .hw_ops = &vfe_ops_480,1086 .formats_rdi = &vfe_formats_rdi_845,1087 .formats_pix = &vfe_formats_pix_8451088 }1089 },1090};1091 1092static const struct resources_icc icc_res_sm8250[] = {1093 {1094 .name = "cam_ahb",1095 .icc_bw_tbl.avg = 38400,1096 .icc_bw_tbl.peak = 76800,1097 },1098 {1099 .name = "cam_hf_0_mnoc",1100 .icc_bw_tbl.avg = 2097152,1101 .icc_bw_tbl.peak = 2097152,1102 },1103 {1104 .name = "cam_sf_0_mnoc",1105 .icc_bw_tbl.avg = 0,1106 .icc_bw_tbl.peak = 2097152,1107 },1108 {1109 .name = "cam_sf_icp_mnoc",1110 .icc_bw_tbl.avg = 2097152,1111 .icc_bw_tbl.peak = 2097152,1112 },1113};1114 1115static const struct camss_subdev_resources csiphy_res_sc8280xp[] = {1116 /* CSIPHY0 */1117 {1118 .regulators = {},1119 .clock = { "csiphy0", "csiphy0_timer" },1120 .clock_rate = { { 400000000 },1121 { 300000000 } },1122 .reg = { "csiphy0" },1123 .interrupt = { "csiphy0" },1124 .csiphy = {1125 .hw_ops = &csiphy_ops_3ph_1_0,1126 .formats = &csiphy_formats_sdm8451127 }1128 },1129 /* CSIPHY1 */1130 {1131 .regulators = {},1132 .clock = { "csiphy1", "csiphy1_timer" },1133 .clock_rate = { { 400000000 },1134 { 300000000 } },1135 .reg = { "csiphy1" },1136 .interrupt = { "csiphy1" },1137 .csiphy = {1138 .hw_ops = &csiphy_ops_3ph_1_0,1139 .formats = &csiphy_formats_sdm8451140 }1141 },1142 /* CSIPHY2 */1143 {1144 .regulators = {},1145 .clock = { "csiphy2", "csiphy2_timer" },1146 .clock_rate = { { 400000000 },1147 { 300000000 } },1148 .reg = { "csiphy2" },1149 .interrupt = { "csiphy2" },1150 .csiphy = {1151 .hw_ops = &csiphy_ops_3ph_1_0,1152 .formats = &csiphy_formats_sdm8451153 }1154 },1155 /* CSIPHY3 */1156 {1157 .regulators = {},1158 .clock = { "csiphy3", "csiphy3_timer" },1159 .clock_rate = { { 400000000 },1160 { 300000000 } },1161 .reg = { "csiphy3" },1162 .interrupt = { "csiphy3" },1163 .csiphy = {1164 .hw_ops = &csiphy_ops_3ph_1_0,1165 .formats = &csiphy_formats_sdm8451166 }1167 },1168};1169 1170static const struct camss_subdev_resources csid_res_sc8280xp[] = {1171 /* CSID0 */1172 {1173 .regulators = { "vdda-phy", "vdda-pll" },1174 .clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0", "vfe0_axi" },1175 .clock_rate = { { 400000000, 480000000, 600000000 },1176 { 0 },1177 { 0 },1178 { 0 } },1179 .reg = { "csid0" },1180 .interrupt = { "csid0" },1181 .csid = {1182 .hw_ops = &csid_ops_gen2,1183 .parent_dev_ops = &vfe_parent_dev_ops,1184 .formats = &csid_formats_gen21185 }1186 },1187 /* CSID1 */1188 {1189 .regulators = { "vdda-phy", "vdda-pll" },1190 .clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1", "vfe1_axi" },1191 .clock_rate = { { 400000000, 480000000, 600000000 },1192 { 0 },1193 { 0 },1194 { 0 } },1195 .reg = { "csid1" },1196 .interrupt = { "csid1" },1197 .csid = {1198 .hw_ops = &csid_ops_gen2,1199 .parent_dev_ops = &vfe_parent_dev_ops,1200 .formats = &csid_formats_gen21201 }1202 },1203 /* CSID2 */1204 {1205 .regulators = { "vdda-phy", "vdda-pll" },1206 .clock = { "vfe2_csid", "vfe2_cphy_rx", "vfe2", "vfe2_axi" },1207 .clock_rate = { { 400000000, 480000000, 600000000 },1208 { 0 },1209 { 0 },1210 { 0 } },1211 .reg = { "csid2" },1212 .interrupt = { "csid2" },1213 .csid = {1214 .hw_ops = &csid_ops_gen2,1215 .parent_dev_ops = &vfe_parent_dev_ops,1216 .formats = &csid_formats_gen21217 }1218 },1219 /* CSID3 */1220 {1221 .regulators = { "vdda-phy", "vdda-pll" },1222 .clock = { "vfe3_csid", "vfe3_cphy_rx", "vfe3", "vfe3_axi" },1223 .clock_rate = { { 400000000, 480000000, 600000000 },1224 { 0 },1225 { 0 },1226 { 0 } },1227 .reg = { "csid3" },1228 .interrupt = { "csid3" },1229 .csid = {1230 .hw_ops = &csid_ops_gen2,1231 .parent_dev_ops = &vfe_parent_dev_ops,1232 .formats = &csid_formats_gen21233 }1234 },1235 /* CSID_LITE0 */1236 {1237 .regulators = { "vdda-phy", "vdda-pll" },1238 .clock = { "vfe_lite0_csid", "vfe_lite0_cphy_rx", "vfe_lite0" },1239 .clock_rate = { { 400000000, 480000000, 600000000 },1240 { 0 },1241 { 0 }, },1242 .reg = { "csid0_lite" },1243 .interrupt = { "csid0_lite" },1244 .csid = {1245 .is_lite = true,1246 .hw_ops = &csid_ops_gen2,1247 .parent_dev_ops = &vfe_parent_dev_ops,1248 .formats = &csid_formats_gen21249 }1250 },1251 /* CSID_LITE1 */1252 {1253 .regulators = { "vdda-phy", "vdda-pll" },1254 .clock = { "vfe_lite1_csid", "vfe_lite1_cphy_rx", "vfe_lite1" },1255 .clock_rate = { { 400000000, 480000000, 600000000 },1256 { 0 },1257 { 0 }, },1258 .reg = { "csid1_lite" },1259 .interrupt = { "csid1_lite" },1260 .csid = {1261 .is_lite = true,1262 .hw_ops = &csid_ops_gen2,1263 .parent_dev_ops = &vfe_parent_dev_ops,1264 .formats = &csid_formats_gen21265 }1266 },1267 /* CSID_LITE2 */1268 {1269 .regulators = { "vdda-phy", "vdda-pll" },1270 .clock = { "vfe_lite2_csid", "vfe_lite2_cphy_rx", "vfe_lite2" },1271 .clock_rate = { { 400000000, 480000000, 600000000 },1272 { 0 },1273 { 0 }, },1274 .reg = { "csid2_lite" },1275 .interrupt = { "csid2_lite" },1276 .csid = {1277 .is_lite = true,1278 .hw_ops = &csid_ops_gen2,1279 .parent_dev_ops = &vfe_parent_dev_ops,1280 .formats = &csid_formats_gen21281 }1282 },1283 /* CSID_LITE3 */1284 {1285 .regulators = { "vdda-phy", "vdda-pll" },1286 .clock = { "vfe_lite3_csid", "vfe_lite3_cphy_rx", "vfe_lite3" },1287 .clock_rate = { { 400000000, 480000000, 600000000 },1288 { 0 },1289 { 0 }, },1290 .reg = { "csid3_lite" },1291 .interrupt = { "csid3_lite" },1292 .csid = {1293 .is_lite = true,1294 .hw_ops = &csid_ops_gen2,1295 .parent_dev_ops = &vfe_parent_dev_ops,1296 .formats = &csid_formats_gen21297 }1298 }1299};1300 1301static const struct camss_subdev_resources vfe_res_sc8280xp[] = {1302 /* VFE0 */1303 {1304 .regulators = {},1305 .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe0", "vfe0_axi" },1306 .clock_rate = { { 0 },1307 { 0 },1308 { 19200000, 80000000},1309 { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 },1310 { 400000000, 558000000, 637000000, 760000000 },1311 { 0 }, },1312 .reg = { "vfe0" },1313 .interrupt = { "vfe0" },1314 .vfe = {1315 .line_num = 4,1316 .pd_name = "ife0",1317 .hw_ops = &vfe_ops_170,1318 .formats_rdi = &vfe_formats_rdi_845,1319 .formats_pix = &vfe_formats_pix_8451320 }1321 },1322 /* VFE1 */1323 {1324 .regulators = {},1325 .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe1", "vfe1_axi" },1326 .clock_rate = { { 0 },1327 { 0 },1328 { 19200000, 80000000},1329 { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 },1330 { 400000000, 558000000, 637000000, 760000000 },1331 { 0 }, },1332 .reg = { "vfe1" },1333 .interrupt = { "vfe1" },1334 .vfe = {1335 .line_num = 4,1336 .pd_name = "ife1",1337 .hw_ops = &vfe_ops_170,1338 .formats_rdi = &vfe_formats_rdi_845,1339 .formats_pix = &vfe_formats_pix_8451340 }1341 },1342 /* VFE2 */1343 {1344 .regulators = {},1345 .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe2", "vfe2_axi" },1346 .clock_rate = { { 0 },1347 { 0 },1348 { 19200000, 80000000},1349 { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 },1350 { 400000000, 558000000, 637000000, 760000000 },1351 { 0 }, },1352 .reg = { "vfe2" },1353 .interrupt = { "vfe2" },1354 .vfe = {1355 .line_num = 4,1356 .pd_name = "ife2",1357 .hw_ops = &vfe_ops_170,1358 .formats_rdi = &vfe_formats_rdi_845,1359 .formats_pix = &vfe_formats_pix_8451360 }1361 },1362 /* VFE3 */1363 {1364 .regulators = {},1365 .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe3", "vfe3_axi" },1366 .clock_rate = { { 0 },1367 { 0 },1368 { 19200000, 80000000},1369 { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 },1370 { 400000000, 558000000, 637000000, 760000000 },1371 { 0 }, },1372 .reg = { "vfe3" },1373 .interrupt = { "vfe3" },1374 .vfe = {1375 .line_num = 4,1376 .pd_name = "ife3",1377 .hw_ops = &vfe_ops_170,1378 .formats_rdi = &vfe_formats_rdi_845,1379 .formats_pix = &vfe_formats_pix_8451380 }1381 },1382 /* VFE_LITE_0 */1383 {1384 .regulators = {},1385 .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite0" },1386 .clock_rate = { { 0 },1387 { 0 },1388 { 19200000, 80000000},1389 { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 },1390 { 320000000, 400000000, 480000000, 600000000 }, },1391 .reg = { "vfe_lite0" },1392 .interrupt = { "vfe_lite0" },1393 .vfe = {1394 .is_lite = true,1395 .line_num = 4,1396 .hw_ops = &vfe_ops_170,1397 .formats_rdi = &vfe_formats_rdi_845,1398 .formats_pix = &vfe_formats_pix_8451399 }1400 },1401 /* VFE_LITE_1 */1402 {1403 .regulators = {},1404 .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite1" },1405 .clock_rate = { { 0 },1406 { 0 },1407 { 19200000, 80000000},1408 { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 },1409 { 320000000, 400000000, 480000000, 600000000 }, },1410 .reg = { "vfe_lite1" },1411 .interrupt = { "vfe_lite1" },1412 .vfe = {1413 .is_lite = true,1414 .line_num = 4,1415 .hw_ops = &vfe_ops_170,1416 .formats_rdi = &vfe_formats_rdi_845,1417 .formats_pix = &vfe_formats_pix_8451418 }1419 },1420 /* VFE_LITE_2 */1421 {1422 .regulators = {},1423 .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite2" },1424 .clock_rate = { { 0 },1425 { 0 },1426 { 19200000, 80000000},1427 { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 },1428 { 320000000, 400000000, 480000000, 600000000, }, },1429 .reg = { "vfe_lite2" },1430 .interrupt = { "vfe_lite2" },1431 .vfe = {1432 .is_lite = true,1433 .line_num = 4,1434 .hw_ops = &vfe_ops_170,1435 .formats_rdi = &vfe_formats_rdi_845,1436 .formats_pix = &vfe_formats_pix_8451437 }1438 },1439 /* VFE_LITE_3 */1440 {1441 .regulators = {},1442 .clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb", "camnoc_axi", "vfe_lite3" },1443 .clock_rate = { { 0 },1444 { 0 },1445 { 19200000, 80000000},1446 { 19200000, 150000000, 266666667, 320000000, 400000000, 480000000 },1447 { 320000000, 400000000, 480000000, 600000000 }, },1448 .reg = { "vfe_lite3" },1449 .interrupt = { "vfe_lite3" },1450 .vfe = {1451 .is_lite = true,1452 .line_num = 4,1453 .hw_ops = &vfe_ops_170,1454 .formats_rdi = &vfe_formats_rdi_845,1455 .formats_pix = &vfe_formats_pix_8451456 }1457 },1458};1459 1460static const struct resources_icc icc_res_sc8280xp[] = {1461 {1462 .name = "cam_ahb",1463 .icc_bw_tbl.avg = 150000,1464 .icc_bw_tbl.peak = 300000,1465 },1466 {1467 .name = "cam_hf_mnoc",1468 .icc_bw_tbl.avg = 2097152,1469 .icc_bw_tbl.peak = 2097152,1470 },1471 {1472 .name = "cam_sf_mnoc",1473 .icc_bw_tbl.avg = 2097152,1474 .icc_bw_tbl.peak = 2097152,1475 },1476 {1477 .name = "cam_sf_icp_mnoc",1478 .icc_bw_tbl.avg = 2097152,1479 .icc_bw_tbl.peak = 2097152,1480 },1481};1482 1483/*1484 * camss_add_clock_margin - Add margin to clock frequency rate1485 * @rate: Clock frequency rate1486 *1487 * When making calculations with physical clock frequency values1488 * some safety margin must be added. Add it.1489 */1490inline void camss_add_clock_margin(u64 *rate)1491{1492 *rate *= CAMSS_CLOCK_MARGIN_NUMERATOR;1493 *rate = div_u64(*rate, CAMSS_CLOCK_MARGIN_DENOMINATOR);1494}1495 1496/*1497 * camss_enable_clocks - Enable multiple clocks1498 * @nclocks: Number of clocks in clock array1499 * @clock: Clock array1500 * @dev: Device1501 *1502 * Return 0 on success or a negative error code otherwise1503 */1504int camss_enable_clocks(int nclocks, struct camss_clock *clock,1505 struct device *dev)1506{1507 int ret;1508 int i;1509 1510 for (i = 0; i < nclocks; i++) {1511 ret = clk_prepare_enable(clock[i].clk);1512 if (ret) {1513 dev_err(dev, "clock enable failed: %d\n", ret);1514 goto error;1515 }1516 }1517 1518 return 0;1519 1520error:1521 for (i--; i >= 0; i--)1522 clk_disable_unprepare(clock[i].clk);1523 1524 return ret;1525}1526 1527/*1528 * camss_disable_clocks - Disable multiple clocks1529 * @nclocks: Number of clocks in clock array1530 * @clock: Clock array1531 */1532void camss_disable_clocks(int nclocks, struct camss_clock *clock)1533{1534 int i;1535 1536 for (i = nclocks - 1; i >= 0; i--)1537 clk_disable_unprepare(clock[i].clk);1538}1539 1540/*1541 * camss_find_sensor - Find a linked media entity which represents a sensor1542 * @entity: Media entity to start searching from1543 *1544 * Return a pointer to sensor media entity or NULL if not found1545 */1546struct media_entity *camss_find_sensor(struct media_entity *entity)1547{1548 struct media_pad *pad;1549 1550 while (1) {1551 pad = &entity->pads[0];1552 if (!(pad->flags & MEDIA_PAD_FL_SINK))1553 return NULL;1554 1555 pad = media_pad_remote_pad_first(pad);1556 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))1557 return NULL;1558 1559 entity = pad->entity;1560 1561 if (entity->function == MEDIA_ENT_F_CAM_SENSOR)1562 return entity;1563 }1564}1565 1566/**1567 * camss_get_link_freq - Get link frequency from sensor1568 * @entity: Media entity in the current pipeline1569 * @bpp: Number of bits per pixel for the current format1570 * @lanes: Number of lanes in the link to the sensor1571 *1572 * Return link frequency on success or a negative error code otherwise1573 */1574s64 camss_get_link_freq(struct media_entity *entity, unsigned int bpp,1575 unsigned int lanes)1576{1577 struct media_entity *sensor;1578 struct v4l2_subdev *subdev;1579 1580 sensor = camss_find_sensor(entity);1581 if (!sensor)1582 return -ENODEV;1583 1584 subdev = media_entity_to_v4l2_subdev(sensor);1585 1586 return v4l2_get_link_freq(subdev->ctrl_handler, bpp, 2 * lanes);1587}1588 1589/*1590 * camss_get_pixel_clock - Get pixel clock rate from sensor1591 * @entity: Media entity in the current pipeline1592 * @pixel_clock: Received pixel clock value1593 *1594 * Return 0 on success or a negative error code otherwise1595 */1596int camss_get_pixel_clock(struct media_entity *entity, u64 *pixel_clock)1597{1598 struct media_entity *sensor;1599 struct v4l2_subdev *subdev;1600 struct v4l2_ctrl *ctrl;1601 1602 sensor = camss_find_sensor(entity);1603 if (!sensor)1604 return -ENODEV;1605 1606 subdev = media_entity_to_v4l2_subdev(sensor);1607 1608 ctrl = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_PIXEL_RATE);1609 1610 if (!ctrl)1611 return -EINVAL;1612 1613 *pixel_clock = v4l2_ctrl_g_ctrl_int64(ctrl);1614 1615 return 0;1616}1617 1618int camss_pm_domain_on(struct camss *camss, int id)1619{1620 int ret = 0;1621 1622 if (id < camss->res->vfe_num) {1623 struct vfe_device *vfe = &camss->vfe[id];1624 1625 ret = vfe->res->hw_ops->pm_domain_on(vfe);1626 }1627 1628 return ret;1629}1630 1631void camss_pm_domain_off(struct camss *camss, int id)1632{1633 if (id < camss->res->vfe_num) {1634 struct vfe_device *vfe = &camss->vfe[id];1635 1636 vfe->res->hw_ops->pm_domain_off(vfe);1637 }1638}1639 1640static int vfe_parent_dev_ops_get(struct camss *camss, int id)1641{1642 int ret = -EINVAL;1643 1644 if (id < camss->res->vfe_num) {1645 struct vfe_device *vfe = &camss->vfe[id];1646 1647 ret = vfe_get(vfe);1648 }1649 1650 return ret;1651}1652 1653static int vfe_parent_dev_ops_put(struct camss *camss, int id)1654{1655 if (id < camss->res->vfe_num) {1656 struct vfe_device *vfe = &camss->vfe[id];1657 1658 vfe_put(vfe);1659 }1660 1661 return 0;1662}1663 1664static void __iomem1665*vfe_parent_dev_ops_get_base_address(struct camss *camss, int id)1666{1667 if (id < camss->res->vfe_num) {1668 struct vfe_device *vfe = &camss->vfe[id];1669 1670 return vfe->base;1671 }1672 1673 return NULL;1674}1675 1676static const struct parent_dev_ops vfe_parent_dev_ops = {1677 .get = vfe_parent_dev_ops_get,1678 .put = vfe_parent_dev_ops_put,1679 .get_base_address = vfe_parent_dev_ops_get_base_address1680};1681 1682/*1683 * camss_of_parse_endpoint_node - Parse port endpoint node1684 * @dev: Device1685 * @node: Device node to be parsed1686 * @csd: Parsed data from port endpoint node1687 *1688 * Return 0 on success or a negative error code on failure1689 */1690static int camss_of_parse_endpoint_node(struct device *dev,1691 struct device_node *node,1692 struct camss_async_subdev *csd)1693{1694 struct csiphy_lanes_cfg *lncfg = &csd->interface.csi2.lane_cfg;1695 struct v4l2_mbus_config_mipi_csi2 *mipi_csi2;1696 struct v4l2_fwnode_endpoint vep = { { 0 } };1697 unsigned int i;1698 int ret;1699 1700 ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep);1701 if (ret)1702 return ret;1703 1704 csd->interface.csiphy_id = vep.base.port;1705 1706 mipi_csi2 = &vep.bus.mipi_csi2;1707 lncfg->clk.pos = mipi_csi2->clock_lane;1708 lncfg->clk.pol = mipi_csi2->lane_polarities[0];1709 lncfg->num_data = mipi_csi2->num_data_lanes;1710 1711 lncfg->data = devm_kcalloc(dev,1712 lncfg->num_data, sizeof(*lncfg->data),1713 GFP_KERNEL);1714 if (!lncfg->data)1715 return -ENOMEM;1716 1717 for (i = 0; i < lncfg->num_data; i++) {1718 lncfg->data[i].pos = mipi_csi2->data_lanes[i];1719 lncfg->data[i].pol = mipi_csi2->lane_polarities[i + 1];1720 }1721 1722 return 0;1723}1724 1725/*1726 * camss_of_parse_ports - Parse ports node1727 * @dev: Device1728 * @notifier: v4l2_device notifier data1729 *1730 * Return number of "port" nodes found in "ports" node1731 */1732static int camss_of_parse_ports(struct camss *camss)1733{1734 struct device *dev = camss->dev;1735 struct device_node *node = NULL;1736 struct device_node *remote = NULL;1737 int ret, num_subdevs = 0;1738 1739 for_each_endpoint_of_node(dev->of_node, node) {1740 struct camss_async_subdev *csd;1741 1742 if (!of_device_is_available(node))1743 continue;1744 1745 remote = of_graph_get_remote_port_parent(node);1746 if (!remote) {1747 dev_err(dev, "Cannot get remote parent\n");1748 ret = -EINVAL;1749 goto err_cleanup;1750 }1751 1752 csd = v4l2_async_nf_add_fwnode(&camss->notifier,1753 of_fwnode_handle(remote),1754 struct camss_async_subdev);1755 of_node_put(remote);1756 if (IS_ERR(csd)) {1757 ret = PTR_ERR(csd);1758 goto err_cleanup;1759 }1760 1761 ret = camss_of_parse_endpoint_node(dev, node, csd);1762 if (ret < 0)1763 goto err_cleanup;1764 1765 num_subdevs++;1766 }1767 1768 return num_subdevs;1769 1770err_cleanup:1771 of_node_put(node);1772 return ret;1773}1774 1775/*1776 * camss_init_subdevices - Initialize subdev structures and resources1777 * @camss: CAMSS device1778 *1779 * Return 0 on success or a negative error code on failure1780 */1781static int camss_init_subdevices(struct camss *camss)1782{1783 const struct camss_resources *res = camss->res;1784 unsigned int i;1785 int ret;1786 1787 for (i = 0; i < camss->res->csiphy_num; i++) {1788 ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i],1789 &res->csiphy_res[i], i);1790 if (ret < 0) {1791 dev_err(camss->dev,1792 "Failed to init csiphy%d sub-device: %d\n",1793 i, ret);1794 return ret;1795 }1796 }1797 1798 /* note: SM8250 requires VFE to be initialized before CSID */1799 for (i = 0; i < camss->res->vfe_num; i++) {1800 ret = msm_vfe_subdev_init(camss, &camss->vfe[i],1801 &res->vfe_res[i], i);1802 if (ret < 0) {1803 dev_err(camss->dev,1804 "Fail to init vfe%d sub-device: %d\n", i, ret);1805 return ret;1806 }1807 }1808 1809 for (i = 0; i < camss->res->csid_num; i++) {1810 ret = msm_csid_subdev_init(camss, &camss->csid[i],1811 &res->csid_res[i], i);1812 if (ret < 0) {1813 dev_err(camss->dev,1814 "Failed to init csid%d sub-device: %d\n",1815 i, ret);1816 return ret;1817 }1818 }1819 1820 ret = msm_ispif_subdev_init(camss, res->ispif_res);1821 if (ret < 0) {1822 dev_err(camss->dev, "Failed to init ispif sub-device: %d\n",1823 ret);1824 return ret;1825 }1826 1827 return 0;1828}1829 1830/*1831 * camss_link_entities - Register subdev nodes and create links1832 * @camss: CAMSS device1833 *1834 * Return 0 on success or a negative error code on failure1835 */1836static int camss_link_entities(struct camss *camss)1837{1838 int i, j, k;1839 int ret;1840 1841 for (i = 0; i < camss->res->csiphy_num; i++) {1842 for (j = 0; j < camss->res->csid_num; j++) {1843 ret = media_create_pad_link(&camss->csiphy[i].subdev.entity,1844 MSM_CSIPHY_PAD_SRC,1845 &camss->csid[j].subdev.entity,1846 MSM_CSID_PAD_SINK,1847 0);1848 if (ret < 0) {1849 dev_err(camss->dev,1850 "Failed to link %s->%s entities: %d\n",1851 camss->csiphy[i].subdev.entity.name,1852 camss->csid[j].subdev.entity.name,1853 ret);1854 return ret;1855 }1856 }1857 }1858 1859 if (camss->ispif) {1860 for (i = 0; i < camss->res->csid_num; i++) {1861 for (j = 0; j < camss->ispif->line_num; j++) {1862 ret = media_create_pad_link(&camss->csid[i].subdev.entity,1863 MSM_CSID_PAD_SRC,1864 &camss->ispif->line[j].subdev.entity,1865 MSM_ISPIF_PAD_SINK,1866 0);1867 if (ret < 0) {1868 dev_err(camss->dev,1869 "Failed to link %s->%s entities: %d\n",1870 camss->csid[i].subdev.entity.name,1871 camss->ispif->line[j].subdev.entity.name,1872 ret);1873 return ret;1874 }1875 }1876 }1877 1878 for (i = 0; i < camss->ispif->line_num; i++)1879 for (k = 0; k < camss->res->vfe_num; k++)1880 for (j = 0; j < camss->vfe[k].res->line_num; j++) {1881 struct v4l2_subdev *ispif = &camss->ispif->line[i].subdev;1882 struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev;1883 1884 ret = media_create_pad_link(&ispif->entity,1885 MSM_ISPIF_PAD_SRC,1886 &vfe->entity,1887 MSM_VFE_PAD_SINK,1888 0);1889 if (ret < 0) {1890 dev_err(camss->dev,1891 "Failed to link %s->%s entities: %d\n",1892 ispif->entity.name,1893 vfe->entity.name,1894 ret);1895 return ret;1896 }1897 }1898 } else {1899 for (i = 0; i < camss->res->csid_num; i++)1900 for (k = 0; k < camss->res->vfe_num; k++)1901 for (j = 0; j < camss->vfe[k].res->line_num; j++) {1902 struct v4l2_subdev *csid = &camss->csid[i].subdev;1903 struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev;1904 1905 ret = media_create_pad_link(&csid->entity,1906 MSM_CSID_PAD_FIRST_SRC + j,1907 &vfe->entity,1908 MSM_VFE_PAD_SINK,1909 0);1910 if (ret < 0) {1911 dev_err(camss->dev,1912 "Failed to link %s->%s entities: %d\n",1913 csid->entity.name,1914 vfe->entity.name,1915 ret);1916 return ret;1917 }1918 }1919 }1920 1921 return 0;1922}1923 1924/*1925 * camss_register_entities - Register subdev nodes and create links1926 * @camss: CAMSS device1927 *1928 * Return 0 on success or a negative error code on failure1929 */1930static int camss_register_entities(struct camss *camss)1931{1932 int i;1933 int ret;1934 1935 for (i = 0; i < camss->res->csiphy_num; i++) {1936 ret = msm_csiphy_register_entity(&camss->csiphy[i],1937 &camss->v4l2_dev);1938 if (ret < 0) {1939 dev_err(camss->dev,1940 "Failed to register csiphy%d entity: %d\n",1941 i, ret);1942 goto err_reg_csiphy;1943 }1944 }1945 1946 for (i = 0; i < camss->res->csid_num; i++) {1947 ret = msm_csid_register_entity(&camss->csid[i],1948 &camss->v4l2_dev);1949 if (ret < 0) {1950 dev_err(camss->dev,1951 "Failed to register csid%d entity: %d\n",1952 i, ret);1953 goto err_reg_csid;1954 }1955 }1956 1957 ret = msm_ispif_register_entities(camss->ispif,1958 &camss->v4l2_dev);1959 if (ret < 0) {1960 dev_err(camss->dev, "Failed to register ispif entities: %d\n", ret);1961 goto err_reg_ispif;1962 }1963 1964 for (i = 0; i < camss->res->vfe_num; i++) {1965 ret = msm_vfe_register_entities(&camss->vfe[i],1966 &camss->v4l2_dev);1967 if (ret < 0) {1968 dev_err(camss->dev,1969 "Failed to register vfe%d entities: %d\n",1970 i, ret);1971 goto err_reg_vfe;1972 }1973 }1974 1975 return 0;1976 1977err_reg_vfe:1978 for (i--; i >= 0; i--)1979 msm_vfe_unregister_entities(&camss->vfe[i]);1980 1981err_reg_ispif:1982 msm_ispif_unregister_entities(camss->ispif);1983 1984 i = camss->res->csid_num;1985err_reg_csid:1986 for (i--; i >= 0; i--)1987 msm_csid_unregister_entity(&camss->csid[i]);1988 1989 i = camss->res->csiphy_num;1990err_reg_csiphy:1991 for (i--; i >= 0; i--)1992 msm_csiphy_unregister_entity(&camss->csiphy[i]);1993 1994 return ret;1995}1996 1997/*1998 * camss_unregister_entities - Unregister subdev nodes1999 * @camss: CAMSS device2000 *2001 * Return 0 on success or a negative error code on failure2002 */2003static void camss_unregister_entities(struct camss *camss)2004{2005 unsigned int i;2006 2007 for (i = 0; i < camss->res->csiphy_num; i++)2008 msm_csiphy_unregister_entity(&camss->csiphy[i]);2009 2010 for (i = 0; i < camss->res->csid_num; i++)2011 msm_csid_unregister_entity(&camss->csid[i]);2012 2013 msm_ispif_unregister_entities(camss->ispif);2014 2015 for (i = 0; i < camss->res->vfe_num; i++)2016 msm_vfe_unregister_entities(&camss->vfe[i]);2017}2018 2019static int camss_subdev_notifier_bound(struct v4l2_async_notifier *async,2020 struct v4l2_subdev *subdev,2021 struct v4l2_async_connection *asd)2022{2023 struct camss *camss = container_of(async, struct camss, notifier);2024 struct camss_async_subdev *csd =2025 container_of(asd, struct camss_async_subdev, asd);2026 u8 id = csd->interface.csiphy_id;2027 struct csiphy_device *csiphy = &camss->csiphy[id];2028 2029 csiphy->cfg.csi2 = &csd->interface.csi2;2030 subdev->host_priv = csiphy;2031 2032 return 0;2033}2034 2035static int camss_subdev_notifier_complete(struct v4l2_async_notifier *async)2036{2037 struct camss *camss = container_of(async, struct camss, notifier);2038 struct v4l2_device *v4l2_dev = &camss->v4l2_dev;2039 struct v4l2_subdev *sd;2040 int ret;2041 2042 list_for_each_entry(sd, &v4l2_dev->subdevs, list) {2043 if (sd->host_priv) {2044 struct media_entity *sensor = &sd->entity;2045 struct csiphy_device *csiphy =2046 (struct csiphy_device *) sd->host_priv;2047 struct media_entity *input = &csiphy->subdev.entity;2048 unsigned int i;2049 2050 for (i = 0; i < sensor->num_pads; i++) {2051 if (sensor->pads[i].flags & MEDIA_PAD_FL_SOURCE)2052 break;2053 }2054 if (i == sensor->num_pads) {2055 dev_err(camss->dev,2056 "No source pad in external entity\n");2057 return -EINVAL;2058 }2059 2060 ret = media_create_pad_link(sensor, i,2061 input, MSM_CSIPHY_PAD_SINK,2062 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);2063 if (ret < 0) {2064 dev_err(camss->dev,2065 "Failed to link %s->%s entities: %d\n",2066 sensor->name, input->name, ret);2067 return ret;2068 }2069 }2070 }2071 2072 ret = v4l2_device_register_subdev_nodes(&camss->v4l2_dev);2073 if (ret < 0)2074 return ret;2075 2076 return media_device_register(&camss->media_dev);2077}2078 2079static const struct v4l2_async_notifier_operations camss_subdev_notifier_ops = {2080 .bound = camss_subdev_notifier_bound,2081 .complete = camss_subdev_notifier_complete,2082};2083 2084static const struct media_device_ops camss_media_ops = {2085 .link_notify = v4l2_pipeline_link_notify,2086};2087 2088static int camss_configure_pd(struct camss *camss)2089{2090 const struct camss_resources *res = camss->res;2091 struct device *dev = camss->dev;2092 int vfepd_num;2093 int i;2094 int ret;2095 2096 camss->genpd_num = of_count_phandle_with_args(dev->of_node,2097 "power-domains",2098 "#power-domain-cells");2099 if (camss->genpd_num < 0) {2100 dev_err(dev, "Power domains are not defined for camss\n");2101 return camss->genpd_num;2102 }2103 2104 /*2105 * If a platform device has just one power domain, then it is attached2106 * at platform_probe() level, thus there shall be no need and even no2107 * option to attach it again, this is the case for CAMSS on MSM8916.2108 */2109 if (camss->genpd_num == 1)2110 return 0;2111 2112 /* count the # of VFEs which have flagged power-domain */2113 for (vfepd_num = i = 0; i < camss->res->vfe_num; i++) {2114 if (res->vfe_res[i].vfe.has_pd)2115 vfepd_num++;2116 }2117 2118 /*2119 * If the number of power-domains is greater than the number of VFEs2120 * then the additional power-domain is for the entire CAMSS block.2121 */2122 if (!(camss->genpd_num > vfepd_num))2123 return 0;2124 2125 /*2126 * If a power-domain name is defined try to use it.2127 * It is possible we are running a new kernel with an old dtb so2128 * fallback to indexes even if a pd_name is defined but not found.2129 */2130 if (camss->res->pd_name) {2131 camss->genpd = dev_pm_domain_attach_by_name(camss->dev,2132 camss->res->pd_name);2133 if (IS_ERR(camss->genpd)) {2134 ret = PTR_ERR(camss->genpd);2135 goto fail_pm;2136 }2137 }2138 2139 if (!camss->genpd) {2140 /*2141 * Legacy magic index. TITAN_TOP GDSC must be the last2142 * item in the power-domain list.2143 */2144 camss->genpd = dev_pm_domain_attach_by_id(camss->dev,2145 camss->genpd_num - 1);2146 }2147 if (IS_ERR_OR_NULL(camss->genpd)) {2148 if (!camss->genpd)2149 ret = -ENODEV;2150 else2151 ret = PTR_ERR(camss->genpd);2152 goto fail_pm;2153 }2154 camss->genpd_link = device_link_add(camss->dev, camss->genpd,2155 DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME |2156 DL_FLAG_RPM_ACTIVE);2157 if (!camss->genpd_link) {2158 ret = -EINVAL;2159 goto fail_pm;2160 }2161 2162 return 0;2163 2164fail_pm:2165 dev_pm_domain_detach(camss->genpd, true);2166 2167 return ret;2168}2169 2170static int camss_icc_get(struct camss *camss)2171{2172 const struct resources_icc *icc_res;2173 int i;2174 2175 icc_res = camss->res->icc_res;2176 2177 for (i = 0; i < camss->res->icc_path_num; i++) {2178 camss->icc_path[i] = devm_of_icc_get(camss->dev,2179 icc_res[i].name);2180 if (IS_ERR(camss->icc_path[i]))2181 return PTR_ERR(camss->icc_path[i]);2182 }2183 2184 return 0;2185}2186 2187static void camss_genpd_subdevice_cleanup(struct camss *camss)2188{2189 int i;2190 2191 for (i = 0; i < camss->res->vfe_num; i++)2192 msm_vfe_genpd_cleanup(&camss->vfe[i]);2193}2194 2195static void camss_genpd_cleanup(struct camss *camss)2196{2197 if (camss->genpd_num == 1)2198 return;2199 2200 camss_genpd_subdevice_cleanup(camss);2201 2202 if (camss->genpd_link)2203 device_link_del(camss->genpd_link);2204 2205 dev_pm_domain_detach(camss->genpd, true);2206}2207 2208/*2209 * camss_probe - Probe CAMSS platform device2210 * @pdev: Pointer to CAMSS platform device2211 *2212 * Return 0 on success or a negative error code on failure2213 */2214static int camss_probe(struct platform_device *pdev)2215{2216 struct device *dev = &pdev->dev;2217 struct camss *camss;2218 int num_subdevs;2219 int ret;2220 2221 camss = devm_kzalloc(dev, sizeof(*camss), GFP_KERNEL);2222 if (!camss)2223 return -ENOMEM;2224 2225 camss->res = of_device_get_match_data(dev);2226 2227 atomic_set(&camss->ref_count, 0);2228 camss->dev = dev;2229 platform_set_drvdata(pdev, camss);2230 2231 camss->csiphy = devm_kcalloc(dev, camss->res->csiphy_num,2232 sizeof(*camss->csiphy), GFP_KERNEL);2233 if (!camss->csiphy)2234 return -ENOMEM;2235 2236 camss->csid = devm_kcalloc(dev, camss->res->csid_num, sizeof(*camss->csid),2237 GFP_KERNEL);2238 if (!camss->csid)2239 return -ENOMEM;2240 2241 if (camss->res->version == CAMSS_8x16 ||2242 camss->res->version == CAMSS_8x96) {2243 camss->ispif = devm_kcalloc(dev, 1, sizeof(*camss->ispif), GFP_KERNEL);2244 if (!camss->ispif)2245 return -ENOMEM;2246 }2247 2248 camss->vfe = devm_kcalloc(dev, camss->res->vfe_num,2249 sizeof(*camss->vfe), GFP_KERNEL);2250 if (!camss->vfe)2251 return -ENOMEM;2252 2253 ret = camss_icc_get(camss);2254 if (ret < 0)2255 return ret;2256 2257 ret = camss_configure_pd(camss);2258 if (ret < 0) {2259 dev_err(dev, "Failed to configure power domains: %d\n", ret);2260 return ret;2261 }2262 2263 ret = camss_init_subdevices(camss);2264 if (ret < 0)2265 goto err_genpd_cleanup;2266 2267 ret = dma_set_mask_and_coherent(dev, 0xffffffff);2268 if (ret)2269 goto err_genpd_cleanup;2270 2271 camss->media_dev.dev = camss->dev;2272 strscpy(camss->media_dev.model, "Qualcomm Camera Subsystem",2273 sizeof(camss->media_dev.model));2274 camss->media_dev.ops = &camss_media_ops;2275 media_device_init(&camss->media_dev);2276 2277 camss->v4l2_dev.mdev = &camss->media_dev;2278 ret = v4l2_device_register(camss->dev, &camss->v4l2_dev);2279 if (ret < 0) {2280 dev_err(dev, "Failed to register V4L2 device: %d\n", ret);2281 goto err_genpd_cleanup;2282 }2283 2284 v4l2_async_nf_init(&camss->notifier, &camss->v4l2_dev);2285 2286 pm_runtime_enable(dev);2287 2288 num_subdevs = camss_of_parse_ports(camss);2289 if (num_subdevs < 0) {2290 ret = num_subdevs;2291 goto err_v4l2_device_unregister;2292 }2293 2294 ret = camss_register_entities(camss);2295 if (ret < 0)2296 goto err_v4l2_device_unregister;2297 2298 ret = camss->res->link_entities(camss);2299 if (ret < 0)2300 goto err_register_subdevs;2301 2302 if (num_subdevs) {2303 camss->notifier.ops = &camss_subdev_notifier_ops;2304 2305 ret = v4l2_async_nf_register(&camss->notifier);2306 if (ret) {2307 dev_err(dev,2308 "Failed to register async subdev nodes: %d\n",2309 ret);2310 goto err_register_subdevs;2311 }2312 } else {2313 ret = v4l2_device_register_subdev_nodes(&camss->v4l2_dev);2314 if (ret < 0) {2315 dev_err(dev, "Failed to register subdev nodes: %d\n",2316 ret);2317 goto err_register_subdevs;2318 }2319 2320 ret = media_device_register(&camss->media_dev);2321 if (ret < 0) {2322 dev_err(dev, "Failed to register media device: %d\n",2323 ret);2324 goto err_register_subdevs;2325 }2326 }2327 2328 return 0;2329 2330err_register_subdevs:2331 camss_unregister_entities(camss);2332err_v4l2_device_unregister:2333 v4l2_device_unregister(&camss->v4l2_dev);2334 v4l2_async_nf_cleanup(&camss->notifier);2335 pm_runtime_disable(dev);2336err_genpd_cleanup:2337 camss_genpd_cleanup(camss);2338 2339 return ret;2340}2341 2342void camss_delete(struct camss *camss)2343{2344 v4l2_device_unregister(&camss->v4l2_dev);2345 media_device_unregister(&camss->media_dev);2346 media_device_cleanup(&camss->media_dev);2347 2348 pm_runtime_disable(camss->dev);2349}2350 2351/*2352 * camss_remove - Remove CAMSS platform device2353 * @pdev: Pointer to CAMSS platform device2354 *2355 * Always returns 0.2356 */2357static void camss_remove(struct platform_device *pdev)2358{2359 struct camss *camss = platform_get_drvdata(pdev);2360 2361 v4l2_async_nf_unregister(&camss->notifier);2362 v4l2_async_nf_cleanup(&camss->notifier);2363 camss_unregister_entities(camss);2364 2365 if (atomic_read(&camss->ref_count) == 0)2366 camss_delete(camss);2367 2368 camss_genpd_cleanup(camss);2369}2370 2371static const struct camss_resources msm8916_resources = {2372 .version = CAMSS_8x16,2373 .csiphy_res = csiphy_res_8x16,2374 .csid_res = csid_res_8x16,2375 .ispif_res = &ispif_res_8x16,2376 .vfe_res = vfe_res_8x16,2377 .csiphy_num = ARRAY_SIZE(csiphy_res_8x16),2378 .csid_num = ARRAY_SIZE(csid_res_8x16),2379 .vfe_num = ARRAY_SIZE(vfe_res_8x16),2380 .link_entities = camss_link_entities2381};2382 2383static const struct camss_resources msm8996_resources = {2384 .version = CAMSS_8x96,2385 .csiphy_res = csiphy_res_8x96,2386 .csid_res = csid_res_8x96,2387 .ispif_res = &ispif_res_8x96,2388 .vfe_res = vfe_res_8x96,2389 .csiphy_num = ARRAY_SIZE(csiphy_res_8x96),2390 .csid_num = ARRAY_SIZE(csid_res_8x96),2391 .vfe_num = ARRAY_SIZE(vfe_res_8x96),2392 .link_entities = camss_link_entities2393};2394 2395static const struct camss_resources sdm660_resources = {2396 .version = CAMSS_660,2397 .csiphy_res = csiphy_res_660,2398 .csid_res = csid_res_660,2399 .ispif_res = &ispif_res_660,2400 .vfe_res = vfe_res_660,2401 .csiphy_num = ARRAY_SIZE(csiphy_res_660),2402 .csid_num = ARRAY_SIZE(csid_res_660),2403 .vfe_num = ARRAY_SIZE(vfe_res_660),2404 .link_entities = camss_link_entities2405};2406 2407static const struct camss_resources sdm845_resources = {2408 .version = CAMSS_845,2409 .csiphy_res = csiphy_res_845,2410 .csid_res = csid_res_845,2411 .vfe_res = vfe_res_845,2412 .csiphy_num = ARRAY_SIZE(csiphy_res_845),2413 .csid_num = ARRAY_SIZE(csid_res_845),2414 .vfe_num = ARRAY_SIZE(vfe_res_845),2415 .link_entities = camss_link_entities2416};2417 2418static const struct camss_resources sm8250_resources = {2419 .version = CAMSS_8250,2420 .pd_name = "top",2421 .csiphy_res = csiphy_res_8250,2422 .csid_res = csid_res_8250,2423 .vfe_res = vfe_res_8250,2424 .icc_res = icc_res_sm8250,2425 .icc_path_num = ARRAY_SIZE(icc_res_sm8250),2426 .csiphy_num = ARRAY_SIZE(csiphy_res_8250),2427 .csid_num = ARRAY_SIZE(csid_res_8250),2428 .vfe_num = ARRAY_SIZE(vfe_res_8250),2429 .link_entities = camss_link_entities2430};2431 2432static const struct camss_resources sc8280xp_resources = {2433 .version = CAMSS_8280XP,2434 .pd_name = "top",2435 .csiphy_res = csiphy_res_sc8280xp,2436 .csid_res = csid_res_sc8280xp,2437 .ispif_res = NULL,2438 .vfe_res = vfe_res_sc8280xp,2439 .icc_res = icc_res_sc8280xp,2440 .icc_path_num = ARRAY_SIZE(icc_res_sc8280xp),2441 .csiphy_num = ARRAY_SIZE(csiphy_res_sc8280xp),2442 .csid_num = ARRAY_SIZE(csid_res_sc8280xp),2443 .vfe_num = ARRAY_SIZE(vfe_res_sc8280xp),2444 .link_entities = camss_link_entities2445};2446 2447static const struct of_device_id camss_dt_match[] = {2448 { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources },2449 { .compatible = "qcom,msm8996-camss", .data = &msm8996_resources },2450 { .compatible = "qcom,sdm660-camss", .data = &sdm660_resources },2451 { .compatible = "qcom,sdm845-camss", .data = &sdm845_resources },2452 { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources },2453 { .compatible = "qcom,sc8280xp-camss", .data = &sc8280xp_resources },2454 { }2455};2456 2457MODULE_DEVICE_TABLE(of, camss_dt_match);2458 2459static int __maybe_unused camss_runtime_suspend(struct device *dev)2460{2461 struct camss *camss = dev_get_drvdata(dev);2462 int i;2463 int ret;2464 2465 for (i = 0; i < camss->res->icc_path_num; i++) {2466 ret = icc_set_bw(camss->icc_path[i], 0, 0);2467 if (ret)2468 return ret;2469 }2470 2471 return 0;2472}2473 2474static int __maybe_unused camss_runtime_resume(struct device *dev)2475{2476 struct camss *camss = dev_get_drvdata(dev);2477 const struct resources_icc *icc_res = camss->res->icc_res;2478 int i;2479 int ret;2480 2481 for (i = 0; i < camss->res->icc_path_num; i++) {2482 ret = icc_set_bw(camss->icc_path[i],2483 icc_res[i].icc_bw_tbl.avg,2484 icc_res[i].icc_bw_tbl.peak);2485 if (ret)2486 return ret;2487 }2488 2489 return 0;2490}2491 2492static const struct dev_pm_ops camss_pm_ops = {2493 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,2494 pm_runtime_force_resume)2495 SET_RUNTIME_PM_OPS(camss_runtime_suspend, camss_runtime_resume, NULL)2496};2497 2498static struct platform_driver qcom_camss_driver = {2499 .probe = camss_probe,2500 .remove_new = camss_remove,2501 .driver = {2502 .name = "qcom-camss",2503 .of_match_table = camss_dt_match,2504 .pm = &camss_pm_ops,2505 },2506};2507 2508module_platform_driver(qcom_camss_driver);2509 2510MODULE_ALIAS("platform:qcom-camss");2511MODULE_DESCRIPTION("Qualcomm Camera Subsystem driver");2512MODULE_AUTHOR("Todor Tomov <todor.tomov@linaro.org>");2513MODULE_LICENSE("GPL v2");2514