1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. 4 */ 5 6 #include <linux/clk-provider.h> 7 #include <linux/module.h> 8 #include <linux/of.h> 9 #include <linux/platform_device.h> 10 #include <linux/pm_runtime.h> 11 #include <linux/regmap.h> 12 13 #include <dt-bindings/clock/qcom,sa8775p-videocc.h> 14 15 #include "clk-alpha-pll.h" 16 #include "clk-branch.h" 17 #include "clk-pll.h" 18 #include "clk-rcg.h" 19 #include "clk-regmap.h" 20 #include "clk-regmap-divider.h" 21 #include "clk-regmap-mux.h" 22 #include "common.h" 23 #include "gdsc.h" 24 #include "reset.h" 25 26 enum { 27 DT_IFACE, 28 DT_BI_TCXO, 29 DT_BI_TCXO_AO, 30 DT_SLEEP_CLK, 31 }; 32 33 enum { 34 P_BI_TCXO, 35 P_BI_TCXO_AO, 36 P_SLEEP_CLK, 37 P_VIDEO_PLL0_OUT_MAIN, 38 P_VIDEO_PLL1_OUT_MAIN, 39 }; 40 41 static const struct pll_vco lucid_evo_vco[] = { 42 { 249600000, 2020000000, 0 }, 43 }; 44 45 static const struct alpha_pll_config video_pll0_config = { 46 .l = 0x39, 47 .alpha = 0x3000, 48 .config_ctl_val = 0x20485699, 49 .config_ctl_hi_val = 0x00182261, 50 .config_ctl_hi1_val = 0x32aa299c, 51 .user_ctl_val = 0x00000000, 52 .user_ctl_hi_val = 0x00400805, 53 }; 54 55 static struct clk_alpha_pll video_pll0 = { 56 .offset = 0x0, 57 .vco_table = lucid_evo_vco, 58 .num_vco = ARRAY_SIZE(lucid_evo_vco), 59 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], 60 .clkr = { 61 .hw.init = &(const struct clk_init_data) { 62 .name = "video_pll0", 63 .parent_data = &(const struct clk_parent_data) { 64 .index = DT_BI_TCXO, 65 }, 66 .num_parents = 1, 67 .ops = &clk_alpha_pll_lucid_evo_ops, 68 }, 69 }, 70 }; 71 72 static const struct alpha_pll_config video_pll1_config = { 73 .l = 0x39, 74 .alpha = 0x3000, 75 .config_ctl_val = 0x20485699, 76 .config_ctl_hi_val = 0x00182261, 77 .config_ctl_hi1_val = 0x32aa299c, 78 .user_ctl_val = 0x00000000, 79 .user_ctl_hi_val = 0x00400805, 80 }; 81 82 static struct clk_alpha_pll video_pll1 = { 83 .offset = 0x1000, 84 .vco_table = lucid_evo_vco, 85 .num_vco = ARRAY_SIZE(lucid_evo_vco), 86 .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_EVO], 87 .clkr = { 88 .hw.init = &(const struct clk_init_data) { 89 .name = "video_pll1", 90 .parent_data = &(const struct clk_parent_data) { 91 .index = DT_BI_TCXO, 92 }, 93 .num_parents = 1, 94 .ops = &clk_alpha_pll_lucid_evo_ops, 95 }, 96 }, 97 }; 98 99 static const struct parent_map video_cc_parent_map_0_ao[] = { 100 { P_BI_TCXO_AO, 0 }, 101 }; 102 103 static const struct clk_parent_data video_cc_parent_data_0_ao[] = { 104 { .index = DT_BI_TCXO_AO }, 105 }; 106 107 static const struct parent_map video_cc_parent_map_1[] = { 108 { P_BI_TCXO, 0 }, 109 { P_VIDEO_PLL0_OUT_MAIN, 1 }, 110 }; 111 112 static const struct clk_parent_data video_cc_parent_data_1[] = { 113 { .index = DT_BI_TCXO }, 114 { .hw = &video_pll0.clkr.hw }, 115 }; 116 117 static const struct parent_map video_cc_parent_map_2[] = { 118 { P_BI_TCXO, 0 }, 119 { P_VIDEO_PLL1_OUT_MAIN, 1 }, 120 }; 121 122 static const struct clk_parent_data video_cc_parent_data_2[] = { 123 { .index = DT_BI_TCXO }, 124 { .hw = &video_pll1.clkr.hw }, 125 }; 126 127 static const struct parent_map video_cc_parent_map_3[] = { 128 { P_SLEEP_CLK, 0 }, 129 }; 130 131 static const struct clk_parent_data video_cc_parent_data_3[] = { 132 { .index = DT_SLEEP_CLK }, 133 }; 134 135 static const struct freq_tbl ftbl_video_cc_ahb_clk_src[] = { 136 F(19200000, P_BI_TCXO_AO, 1, 0, 0), 137 { } 138 }; 139 140 static struct clk_rcg2 video_cc_ahb_clk_src = { 141 .cmd_rcgr = 0x8030, 142 .mnd_width = 0, 143 .hid_width = 5, 144 .parent_map = video_cc_parent_map_0_ao, 145 .freq_tbl = ftbl_video_cc_ahb_clk_src, 146 .clkr.hw.init = &(const struct clk_init_data) { 147 .name = "video_cc_ahb_clk_src", 148 .parent_data = video_cc_parent_data_0_ao, 149 .num_parents = ARRAY_SIZE(video_cc_parent_data_0_ao), 150 .flags = CLK_SET_RATE_PARENT, 151 .ops = &clk_rcg2_shared_ops, 152 }, 153 }; 154 155 static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = { 156 F(1098000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), 157 F(1332000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), 158 F(1599000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), 159 F(1680000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), 160 { } 161 }; 162 163 static struct clk_rcg2 video_cc_mvs0_clk_src = { 164 .cmd_rcgr = 0x8000, 165 .mnd_width = 0, 166 .hid_width = 5, 167 .parent_map = video_cc_parent_map_1, 168 .freq_tbl = ftbl_video_cc_mvs0_clk_src, 169 .clkr.hw.init = &(const struct clk_init_data) { 170 .name = "video_cc_mvs0_clk_src", 171 .parent_data = video_cc_parent_data_1, 172 .num_parents = ARRAY_SIZE(video_cc_parent_data_1), 173 .flags = CLK_SET_RATE_PARENT, 174 .ops = &clk_rcg2_shared_ops, 175 }, 176 }; 177 178 static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = { 179 F(1098000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0), 180 F(1332000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0), 181 F(1600000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0), 182 F(1800000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0), 183 { } 184 }; 185 186 static struct clk_rcg2 video_cc_mvs1_clk_src = { 187 .cmd_rcgr = 0x8018, 188 .mnd_width = 0, 189 .hid_width = 5, 190 .parent_map = video_cc_parent_map_2, 191 .freq_tbl = ftbl_video_cc_mvs1_clk_src, 192 .clkr.hw.init = &(const struct clk_init_data) { 193 .name = "video_cc_mvs1_clk_src", 194 .parent_data = video_cc_parent_data_2, 195 .num_parents = ARRAY_SIZE(video_cc_parent_data_2), 196 .flags = CLK_SET_RATE_PARENT, 197 .ops = &clk_rcg2_shared_ops, 198 }, 199 }; 200 201 static const struct freq_tbl ftbl_video_cc_sleep_clk_src[] = { 202 F(32000, P_SLEEP_CLK, 1, 0, 0), 203 { } 204 }; 205 206 static struct clk_rcg2 video_cc_sleep_clk_src = { 207 .cmd_rcgr = 0x812c, 208 .mnd_width = 0, 209 .hid_width = 5, 210 .parent_map = video_cc_parent_map_3, 211 .freq_tbl = ftbl_video_cc_sleep_clk_src, 212 .clkr.hw.init = &(const struct clk_init_data) { 213 .name = "video_cc_sleep_clk_src", 214 .parent_data = video_cc_parent_data_3, 215 .num_parents = ARRAY_SIZE(video_cc_parent_data_3), 216 .flags = CLK_SET_RATE_PARENT, 217 .ops = &clk_rcg2_shared_ops, 218 }, 219 }; 220 221 static struct clk_rcg2 video_cc_xo_clk_src = { 222 .cmd_rcgr = 0x8110, 223 .mnd_width = 0, 224 .hid_width = 5, 225 .parent_map = video_cc_parent_map_0_ao, 226 .freq_tbl = ftbl_video_cc_ahb_clk_src, 227 .clkr.hw.init = &(const struct clk_init_data) { 228 .name = "video_cc_xo_clk_src", 229 .parent_data = video_cc_parent_data_0_ao, 230 .num_parents = ARRAY_SIZE(video_cc_parent_data_0_ao), 231 .flags = CLK_SET_RATE_PARENT, 232 .ops = &clk_rcg2_shared_ops, 233 }, 234 }; 235 236 static struct clk_regmap_div video_cc_mvs0_div_clk_src = { 237 .reg = 0x80b8, 238 .shift = 0, 239 .width = 4, 240 .clkr.hw.init = &(const struct clk_init_data) { 241 .name = "video_cc_mvs0_div_clk_src", 242 .parent_hws = (const struct clk_hw*[]) { 243 &video_cc_mvs0_clk_src.clkr.hw, 244 }, 245 .num_parents = 1, 246 .flags = CLK_SET_RATE_PARENT, 247 .ops = &clk_regmap_div_ro_ops, 248 }, 249 }; 250 251 static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = { 252 .reg = 0x806c, 253 .shift = 0, 254 .width = 4, 255 .clkr.hw.init = &(const struct clk_init_data) { 256 .name = "video_cc_mvs0c_div2_div_clk_src", 257 .parent_hws = (const struct clk_hw*[]) { 258 &video_cc_mvs0_clk_src.clkr.hw, 259 }, 260 .num_parents = 1, 261 .flags = CLK_SET_RATE_PARENT, 262 .ops = &clk_regmap_div_ro_ops, 263 }, 264 }; 265 266 static struct clk_regmap_div video_cc_mvs1_div_clk_src = { 267 .reg = 0x80dc, 268 .shift = 0, 269 .width = 4, 270 .clkr.hw.init = &(const struct clk_init_data) { 271 .name = "video_cc_mvs1_div_clk_src", 272 .parent_hws = (const struct clk_hw*[]) { 273 &video_cc_mvs1_clk_src.clkr.hw, 274 }, 275 .num_parents = 1, 276 .flags = CLK_SET_RATE_PARENT, 277 .ops = &clk_regmap_div_ro_ops, 278 }, 279 }; 280 281 static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = { 282 .reg = 0x8094, 283 .shift = 0, 284 .width = 4, 285 .clkr.hw.init = &(const struct clk_init_data) { 286 .name = "video_cc_mvs1c_div2_div_clk_src", 287 .parent_hws = (const struct clk_hw*[]) { 288 &video_cc_mvs1_clk_src.clkr.hw, 289 }, 290 .num_parents = 1, 291 .flags = CLK_SET_RATE_PARENT, 292 .ops = &clk_regmap_div_ro_ops, 293 }, 294 }; 295 296 static struct clk_regmap_div video_cc_sm_div_clk_src = { 297 .reg = 0x8108, 298 .shift = 0, 299 .width = 4, 300 .clkr.hw.init = &(const struct clk_init_data) { 301 .name = "video_cc_sm_div_clk_src", 302 .ops = &clk_regmap_div_ro_ops, 303 }, 304 }; 305 306 static struct clk_branch video_cc_mvs0_clk = { 307 .halt_reg = 0x80b0, 308 .halt_check = BRANCH_HALT_VOTED, 309 .hwcg_reg = 0x80b0, 310 .hwcg_bit = 1, 311 .clkr = { 312 .enable_reg = 0x80b0, 313 .enable_mask = BIT(0), 314 .hw.init = &(const struct clk_init_data) { 315 .name = "video_cc_mvs0_clk", 316 .parent_hws = (const struct clk_hw*[]) { 317 &video_cc_mvs0_div_clk_src.clkr.hw, 318 }, 319 .num_parents = 1, 320 .flags = CLK_SET_RATE_PARENT, 321 .ops = &clk_branch2_ops, 322 }, 323 }, 324 }; 325 326 static struct clk_branch video_cc_mvs0c_clk = { 327 .halt_reg = 0x8064, 328 .halt_check = BRANCH_HALT, 329 .clkr = { 330 .enable_reg = 0x8064, 331 .enable_mask = BIT(0), 332 .hw.init = &(const struct clk_init_data) { 333 .name = "video_cc_mvs0c_clk", 334 .parent_hws = (const struct clk_hw*[]) { 335 &video_cc_mvs0c_div2_div_clk_src.clkr.hw, 336 }, 337 .num_parents = 1, 338 .flags = CLK_SET_RATE_PARENT, 339 .ops = &clk_branch2_ops, 340 }, 341 }, 342 }; 343 344 static struct clk_branch video_cc_mvs1_clk = { 345 .halt_reg = 0x80d4, 346 .halt_check = BRANCH_HALT_VOTED, 347 .hwcg_reg = 0x80d4, 348 .hwcg_bit = 1, 349 .clkr = { 350 .enable_reg = 0x80d4, 351 .enable_mask = BIT(0), 352 .hw.init = &(const struct clk_init_data) { 353 .name = "video_cc_mvs1_clk", 354 .parent_hws = (const struct clk_hw*[]) { 355 &video_cc_mvs1_div_clk_src.clkr.hw, 356 }, 357 .num_parents = 1, 358 .flags = CLK_SET_RATE_PARENT, 359 .ops = &clk_branch2_ops, 360 }, 361 }, 362 }; 363 364 static struct clk_branch video_cc_mvs1c_clk = { 365 .halt_reg = 0x808c, 366 .halt_check = BRANCH_HALT, 367 .clkr = { 368 .enable_reg = 0x808c, 369 .enable_mask = BIT(0), 370 .hw.init = &(const struct clk_init_data) { 371 .name = "video_cc_mvs1c_clk", 372 .parent_hws = (const struct clk_hw*[]) { 373 &video_cc_mvs1c_div2_div_clk_src.clkr.hw, 374 }, 375 .num_parents = 1, 376 .flags = CLK_SET_RATE_PARENT, 377 .ops = &clk_branch2_ops, 378 }, 379 }, 380 }; 381 382 static struct clk_branch video_cc_pll_lock_monitor_clk = { 383 .halt_reg = 0x9000, 384 .halt_check = BRANCH_HALT, 385 .clkr = { 386 .enable_reg = 0x9000, 387 .enable_mask = BIT(0), 388 .hw.init = &(const struct clk_init_data) { 389 .name = "video_cc_pll_lock_monitor_clk", 390 .parent_hws = (const struct clk_hw*[]) { 391 &video_cc_xo_clk_src.clkr.hw, 392 }, 393 .num_parents = 1, 394 .flags = CLK_SET_RATE_PARENT, 395 .ops = &clk_branch2_ops, 396 }, 397 }, 398 }; 399 400 static struct clk_branch video_cc_sm_obs_clk = { 401 .halt_reg = 0x810c, 402 .halt_check = BRANCH_HALT_SKIP, 403 .clkr = { 404 .enable_reg = 0x810c, 405 .enable_mask = BIT(0), 406 .hw.init = &(const struct clk_init_data) { 407 .name = "video_cc_sm_obs_clk", 408 .parent_hws = (const struct clk_hw*[]) { 409 &video_cc_sm_div_clk_src.clkr.hw, 410 }, 411 .num_parents = 1, 412 .flags = CLK_SET_RATE_PARENT, 413 .ops = &clk_branch2_ops, 414 }, 415 }, 416 }; 417 418 static struct gdsc video_cc_mvs0c_gdsc = { 419 .gdscr = 0x804c, 420 .en_rest_wait_val = 0x2, 421 .en_few_wait_val = 0x2, 422 .clk_dis_wait_val = 0x6, 423 .pd = { 424 .name = "video_cc_mvs0c_gdsc", 425 }, 426 .pwrsts = PWRSTS_OFF_ON, 427 .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR, 428 }; 429 430 static struct gdsc video_cc_mvs0_gdsc = { 431 .gdscr = 0x809c, 432 .en_rest_wait_val = 0x2, 433 .en_few_wait_val = 0x2, 434 .clk_dis_wait_val = 0x6, 435 .pd = { 436 .name = "video_cc_mvs0_gdsc", 437 }, 438 .pwrsts = PWRSTS_OFF_ON, 439 .parent = &video_cc_mvs0c_gdsc.pd, 440 .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR | HW_CTRL_TRIGGER, 441 }; 442 443 static struct gdsc video_cc_mvs1c_gdsc = { 444 .gdscr = 0x8074, 445 .en_rest_wait_val = 0x2, 446 .en_few_wait_val = 0x2, 447 .clk_dis_wait_val = 0x6, 448 .pd = { 449 .name = "video_cc_mvs1c_gdsc", 450 }, 451 .pwrsts = PWRSTS_OFF_ON, 452 .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR, 453 }; 454 455 static struct gdsc video_cc_mvs1_gdsc = { 456 .gdscr = 0x80c0, 457 .en_rest_wait_val = 0x2, 458 .en_few_wait_val = 0x2, 459 .clk_dis_wait_val = 0x6, 460 .pd = { 461 .name = "video_cc_mvs1_gdsc", 462 }, 463 .pwrsts = PWRSTS_OFF_ON, 464 .parent = &video_cc_mvs1c_gdsc.pd, 465 .flags = RETAIN_FF_ENABLE | POLL_CFG_GDSCR | HW_CTRL_TRIGGER, 466 }; 467 468 static struct clk_regmap *video_cc_sa8775p_clocks[] = { 469 [VIDEO_CC_AHB_CLK_SRC] = &video_cc_ahb_clk_src.clkr, 470 [VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr, 471 [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr, 472 [VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr, 473 [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr, 474 [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr, 475 [VIDEO_CC_MVS1_CLK] = &video_cc_mvs1_clk.clkr, 476 [VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr, 477 [VIDEO_CC_MVS1_DIV_CLK_SRC] = &video_cc_mvs1_div_clk_src.clkr, 478 [VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr, 479 [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr, 480 [VIDEO_CC_PLL_LOCK_MONITOR_CLK] = &video_cc_pll_lock_monitor_clk.clkr, 481 [VIDEO_CC_SLEEP_CLK_SRC] = &video_cc_sleep_clk_src.clkr, 482 [VIDEO_CC_SM_DIV_CLK_SRC] = &video_cc_sm_div_clk_src.clkr, 483 [VIDEO_CC_SM_OBS_CLK] = &video_cc_sm_obs_clk.clkr, 484 [VIDEO_CC_XO_CLK_SRC] = &video_cc_xo_clk_src.clkr, 485 [VIDEO_PLL0] = &video_pll0.clkr, 486 [VIDEO_PLL1] = &video_pll1.clkr, 487 }; 488 489 static struct gdsc *video_cc_sa8775p_gdscs[] = { 490 [VIDEO_CC_MVS0_GDSC] = &video_cc_mvs0_gdsc, 491 [VIDEO_CC_MVS0C_GDSC] = &video_cc_mvs0c_gdsc, 492 [VIDEO_CC_MVS1_GDSC] = &video_cc_mvs1_gdsc, 493 [VIDEO_CC_MVS1C_GDSC] = &video_cc_mvs1c_gdsc, 494 }; 495 496 static const struct qcom_reset_map video_cc_sa8775p_resets[] = { 497 [VIDEO_CC_INTERFACE_BCR] = { 0x80e8 }, 498 [VIDEO_CC_MVS0_BCR] = { 0x8098 }, 499 [VIDEO_CC_MVS0C_CLK_ARES] = { 0x8064, 2 }, 500 [VIDEO_CC_MVS0C_BCR] = { 0x8048 }, 501 [VIDEO_CC_MVS1_BCR] = { 0x80bc }, 502 [VIDEO_CC_MVS1C_CLK_ARES] = { 0x808c, 2 }, 503 [VIDEO_CC_MVS1C_BCR] = { 0x8070 }, 504 }; 505 506 static const struct regmap_config video_cc_sa8775p_regmap_config = { 507 .reg_bits = 32, 508 .reg_stride = 4, 509 .val_bits = 32, 510 .max_register = 0xb000, 511 .fast_io = true, 512 }; 513 514 static const struct qcom_cc_desc video_cc_sa8775p_desc = { 515 .config = &video_cc_sa8775p_regmap_config, 516 .clks = video_cc_sa8775p_clocks, 517 .num_clks = ARRAY_SIZE(video_cc_sa8775p_clocks), 518 .resets = video_cc_sa8775p_resets, 519 .num_resets = ARRAY_SIZE(video_cc_sa8775p_resets), 520 .gdscs = video_cc_sa8775p_gdscs, 521 .num_gdscs = ARRAY_SIZE(video_cc_sa8775p_gdscs), 522 }; 523 524 static const struct of_device_id video_cc_sa8775p_match_table[] = { 525 { .compatible = "qcom,qcs8300-videocc" }, 526 { .compatible = "qcom,sa8775p-videocc" }, 527 { } 528 }; 529 MODULE_DEVICE_TABLE(of, video_cc_sa8775p_match_table); 530 531 static int video_cc_sa8775p_probe(struct platform_device *pdev) 532 { 533 struct regmap *regmap; 534 int ret; 535 536 ret = devm_pm_runtime_enable(&pdev->dev); 537 if (ret) 538 return ret; 539 540 ret = pm_runtime_resume_and_get(&pdev->dev); 541 if (ret) 542 return ret; 543 544 regmap = qcom_cc_map(pdev, &video_cc_sa8775p_desc); 545 if (IS_ERR(regmap)) { 546 pm_runtime_put(&pdev->dev); 547 return PTR_ERR(regmap); 548 } 549 550 clk_lucid_evo_pll_configure(&video_pll0, regmap, &video_pll0_config); 551 clk_lucid_evo_pll_configure(&video_pll1, regmap, &video_pll1_config); 552 553 /* 554 * Set mvs0c clock divider to div-3 to make the mvs0 and 555 * mvs0c clocks to run at the same frequency on QCS8300 556 */ 557 if (of_device_is_compatible(pdev->dev.of_node, "qcom,qcs8300-videocc")) 558 regmap_write(regmap, video_cc_mvs0c_div2_div_clk_src.reg, 2); 559 560 /* Keep some clocks always enabled */ 561 qcom_branch_set_clk_en(regmap, 0x80ec); /* VIDEO_CC_AHB_CLK */ 562 qcom_branch_set_clk_en(regmap, 0x8144); /* VIDEO_CC_SLEEP_CLK */ 563 qcom_branch_set_clk_en(regmap, 0x8128); /* VIDEO_CC_XO_CLK */ 564 565 ret = qcom_cc_really_probe(&pdev->dev, &video_cc_sa8775p_desc, regmap); 566 567 pm_runtime_put(&pdev->dev); 568 569 return ret; 570 } 571 572 static struct platform_driver video_cc_sa8775p_driver = { 573 .probe = video_cc_sa8775p_probe, 574 .driver = { 575 .name = "videocc-sa8775p", 576 .of_match_table = video_cc_sa8775p_match_table, 577 }, 578 }; 579 580 module_platform_driver(video_cc_sa8775p_driver); 581 582 MODULE_DESCRIPTION("QTI VIDEOCC SA8775P Driver"); 583 MODULE_LICENSE("GPL"); 584