1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
6 #include <linux/clk-provider.h>
7 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/regmap.h>
10 #include <linux/reset-controller.h>
12 #include <dt-bindings/clock/qcom,dispcc-sdm845.h>
14 #include "clk-alpha-pll.h"
15 #include "clk-branch.h"
17 #include "clk-regmap-divider.h"
24 P_CORE_BI_PLL_TEST_SE
,
25 P_DISP_CC_PLL0_OUT_MAIN
,
26 P_DSI0_PHY_PLL_OUT_BYTECLK
,
27 P_DSI0_PHY_PLL_OUT_DSICLK
,
28 P_DSI1_PHY_PLL_OUT_BYTECLK
,
29 P_DSI1_PHY_PLL_OUT_DSICLK
,
34 static const struct parent_map disp_cc_parent_map_0
[] = {
36 { P_DSI0_PHY_PLL_OUT_BYTECLK
, 1 },
37 { P_DSI1_PHY_PLL_OUT_BYTECLK
, 2 },
38 { P_CORE_BI_PLL_TEST_SE
, 7 },
41 static const char * const disp_cc_parent_names_0
[] = {
43 "dsi0_phy_pll_out_byteclk",
44 "dsi1_phy_pll_out_byteclk",
45 "core_bi_pll_test_se",
48 static const struct parent_map disp_cc_parent_map_2
[] = {
50 { P_CORE_BI_PLL_TEST_SE
, 7 },
53 static const char * const disp_cc_parent_names_2
[] = {
55 "core_bi_pll_test_se",
58 static const struct parent_map disp_cc_parent_map_3
[] = {
60 { P_DISP_CC_PLL0_OUT_MAIN
, 1 },
61 { P_GPLL0_OUT_MAIN
, 4 },
62 { P_GPLL0_OUT_MAIN_DIV
, 5 },
63 { P_CORE_BI_PLL_TEST_SE
, 7 },
66 static const char * const disp_cc_parent_names_3
[] = {
69 "gcc_disp_gpll0_clk_src",
70 "gcc_disp_gpll0_div_clk_src",
71 "core_bi_pll_test_se",
74 static const struct parent_map disp_cc_parent_map_4
[] = {
76 { P_DSI0_PHY_PLL_OUT_DSICLK
, 1 },
77 { P_DSI1_PHY_PLL_OUT_DSICLK
, 2 },
78 { P_CORE_BI_PLL_TEST_SE
, 7 },
81 static const char * const disp_cc_parent_names_4
[] = {
83 "dsi0_phy_pll_out_dsiclk",
84 "dsi1_phy_pll_out_dsiclk",
85 "core_bi_pll_test_se",
88 static struct clk_alpha_pll disp_cc_pll0
= {
90 .regs
= clk_alpha_pll_regs
[CLK_ALPHA_PLL_TYPE_FABIA
],
92 .hw
.init
= &(struct clk_init_data
){
93 .name
= "disp_cc_pll0",
94 .parent_names
= (const char *[]){ "bi_tcxo" },
96 .ops
= &clk_alpha_pll_fabia_ops
,
101 /* Return the HW recalc rate for idle use case */
102 static struct clk_rcg2 disp_cc_mdss_byte0_clk_src
= {
106 .parent_map
= disp_cc_parent_map_0
,
107 .clkr
.hw
.init
= &(struct clk_init_data
){
108 .name
= "disp_cc_mdss_byte0_clk_src",
109 .parent_names
= disp_cc_parent_names_0
,
111 .flags
= CLK_SET_RATE_PARENT
,
112 .ops
= &clk_byte2_ops
,
116 /* Return the HW recalc rate for idle use case */
117 static struct clk_rcg2 disp_cc_mdss_byte1_clk_src
= {
121 .parent_map
= disp_cc_parent_map_0
,
122 .clkr
.hw
.init
= &(struct clk_init_data
){
123 .name
= "disp_cc_mdss_byte1_clk_src",
124 .parent_names
= disp_cc_parent_names_0
,
126 .flags
= CLK_SET_RATE_PARENT
,
127 .ops
= &clk_byte2_ops
,
131 static const struct freq_tbl ftbl_disp_cc_mdss_esc0_clk_src
[] = {
132 F(19200000, P_BI_TCXO
, 1, 0, 0),
136 static struct clk_rcg2 disp_cc_mdss_esc0_clk_src
= {
140 .parent_map
= disp_cc_parent_map_0
,
141 .freq_tbl
= ftbl_disp_cc_mdss_esc0_clk_src
,
142 .clkr
.hw
.init
= &(struct clk_init_data
){
143 .name
= "disp_cc_mdss_esc0_clk_src",
144 .parent_names
= disp_cc_parent_names_0
,
146 .ops
= &clk_rcg2_ops
,
150 static struct clk_rcg2 disp_cc_mdss_esc1_clk_src
= {
154 .parent_map
= disp_cc_parent_map_0
,
155 .freq_tbl
= ftbl_disp_cc_mdss_esc0_clk_src
,
156 .clkr
.hw
.init
= &(struct clk_init_data
){
157 .name
= "disp_cc_mdss_esc1_clk_src",
158 .parent_names
= disp_cc_parent_names_0
,
160 .ops
= &clk_rcg2_ops
,
164 static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src
[] = {
165 F(19200000, P_BI_TCXO
, 1, 0, 0),
166 F(85714286, P_GPLL0_OUT_MAIN
, 7, 0, 0),
167 F(100000000, P_GPLL0_OUT_MAIN
, 6, 0, 0),
168 F(150000000, P_GPLL0_OUT_MAIN
, 4, 0, 0),
169 F(171428571, P_GPLL0_OUT_MAIN
, 3.5, 0, 0),
170 F(200000000, P_GPLL0_OUT_MAIN
, 3, 0, 0),
171 F(300000000, P_GPLL0_OUT_MAIN
, 2, 0, 0),
172 F(344000000, P_DISP_CC_PLL0_OUT_MAIN
, 2.5, 0, 0),
173 F(430000000, P_DISP_CC_PLL0_OUT_MAIN
, 2, 0, 0),
177 static struct clk_rcg2 disp_cc_mdss_mdp_clk_src
= {
181 .parent_map
= disp_cc_parent_map_3
,
182 .freq_tbl
= ftbl_disp_cc_mdss_mdp_clk_src
,
183 .clkr
.hw
.init
= &(struct clk_init_data
){
184 .name
= "disp_cc_mdss_mdp_clk_src",
185 .parent_names
= disp_cc_parent_names_3
,
187 .ops
= &clk_rcg2_shared_ops
,
191 /* Return the HW recalc rate for idle use case */
192 static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src
= {
196 .parent_map
= disp_cc_parent_map_4
,
197 .clkr
.hw
.init
= &(struct clk_init_data
){
198 .name
= "disp_cc_mdss_pclk0_clk_src",
199 .parent_names
= disp_cc_parent_names_4
,
201 .flags
= CLK_SET_RATE_PARENT
,
202 .ops
= &clk_pixel_ops
,
206 /* Return the HW recalc rate for idle use case */
207 static struct clk_rcg2 disp_cc_mdss_pclk1_clk_src
= {
211 .parent_map
= disp_cc_parent_map_4
,
212 .clkr
.hw
.init
= &(struct clk_init_data
){
213 .name
= "disp_cc_mdss_pclk1_clk_src",
214 .parent_names
= disp_cc_parent_names_4
,
216 .flags
= CLK_SET_RATE_PARENT
,
217 .ops
= &clk_pixel_ops
,
221 static const struct freq_tbl ftbl_disp_cc_mdss_rot_clk_src
[] = {
222 F(19200000, P_BI_TCXO
, 1, 0, 0),
223 F(171428571, P_GPLL0_OUT_MAIN
, 3.5, 0, 0),
224 F(300000000, P_GPLL0_OUT_MAIN
, 2, 0, 0),
225 F(344000000, P_DISP_CC_PLL0_OUT_MAIN
, 2.5, 0, 0),
226 F(430000000, P_DISP_CC_PLL0_OUT_MAIN
, 2, 0, 0),
230 static struct clk_rcg2 disp_cc_mdss_rot_clk_src
= {
234 .parent_map
= disp_cc_parent_map_3
,
235 .freq_tbl
= ftbl_disp_cc_mdss_rot_clk_src
,
236 .clkr
.hw
.init
= &(struct clk_init_data
){
237 .name
= "disp_cc_mdss_rot_clk_src",
238 .parent_names
= disp_cc_parent_names_3
,
240 .ops
= &clk_rcg2_shared_ops
,
244 static struct clk_rcg2 disp_cc_mdss_vsync_clk_src
= {
248 .parent_map
= disp_cc_parent_map_2
,
249 .freq_tbl
= ftbl_disp_cc_mdss_esc0_clk_src
,
250 .clkr
.hw
.init
= &(struct clk_init_data
){
251 .name
= "disp_cc_mdss_vsync_clk_src",
252 .parent_names
= disp_cc_parent_names_2
,
254 .ops
= &clk_rcg2_ops
,
258 static struct clk_branch disp_cc_mdss_ahb_clk
= {
260 .halt_check
= BRANCH_HALT
,
262 .enable_reg
= 0x4004,
263 .enable_mask
= BIT(0),
264 .hw
.init
= &(struct clk_init_data
){
265 .name
= "disp_cc_mdss_ahb_clk",
266 .ops
= &clk_branch2_ops
,
271 static struct clk_branch disp_cc_mdss_axi_clk
= {
273 .halt_check
= BRANCH_HALT
,
275 .enable_reg
= 0x4008,
276 .enable_mask
= BIT(0),
277 .hw
.init
= &(struct clk_init_data
){
278 .name
= "disp_cc_mdss_axi_clk",
279 .ops
= &clk_branch2_ops
,
284 /* Return the HW recalc rate for idle use case */
285 static struct clk_branch disp_cc_mdss_byte0_clk
= {
287 .halt_check
= BRANCH_HALT
,
289 .enable_reg
= 0x2028,
290 .enable_mask
= BIT(0),
291 .hw
.init
= &(struct clk_init_data
){
292 .name
= "disp_cc_mdss_byte0_clk",
293 .parent_names
= (const char *[]){
294 "disp_cc_mdss_byte0_clk_src",
297 .flags
= CLK_SET_RATE_PARENT
,
298 .ops
= &clk_branch2_ops
,
303 /* Return the HW recalc rate for idle use case */
304 static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src
= {
309 .hw
.init
= &(struct clk_init_data
){
310 .name
= "disp_cc_mdss_byte0_div_clk_src",
311 .parent_names
= (const char *[]){
312 "disp_cc_mdss_byte0_clk_src",
315 .ops
= &clk_regmap_div_ops
,
320 /* Return the HW recalc rate for idle use case */
321 static struct clk_branch disp_cc_mdss_byte0_intf_clk
= {
323 .halt_check
= BRANCH_HALT
,
325 .enable_reg
= 0x202c,
326 .enable_mask
= BIT(0),
327 .hw
.init
= &(struct clk_init_data
){
328 .name
= "disp_cc_mdss_byte0_intf_clk",
329 .parent_names
= (const char *[]){
330 "disp_cc_mdss_byte0_div_clk_src",
333 .flags
= CLK_SET_RATE_PARENT
,
334 .ops
= &clk_branch2_ops
,
339 /* Return the HW recalc rate for idle use case */
340 static struct clk_branch disp_cc_mdss_byte1_clk
= {
342 .halt_check
= BRANCH_HALT
,
344 .enable_reg
= 0x2030,
345 .enable_mask
= BIT(0),
346 .hw
.init
= &(struct clk_init_data
){
347 .name
= "disp_cc_mdss_byte1_clk",
348 .parent_names
= (const char *[]){
349 "disp_cc_mdss_byte1_clk_src",
352 .flags
= CLK_SET_RATE_PARENT
,
353 .ops
= &clk_branch2_ops
,
358 /* Return the HW recalc rate for idle use case */
359 static struct clk_regmap_div disp_cc_mdss_byte1_div_clk_src
= {
364 .hw
.init
= &(struct clk_init_data
){
365 .name
= "disp_cc_mdss_byte1_div_clk_src",
366 .parent_names
= (const char *[]){
367 "disp_cc_mdss_byte1_clk_src",
370 .ops
= &clk_regmap_div_ops
,
375 /* Return the HW recalc rate for idle use case */
376 static struct clk_branch disp_cc_mdss_byte1_intf_clk
= {
378 .halt_check
= BRANCH_HALT
,
380 .enable_reg
= 0x2034,
381 .enable_mask
= BIT(0),
382 .hw
.init
= &(struct clk_init_data
){
383 .name
= "disp_cc_mdss_byte1_intf_clk",
384 .parent_names
= (const char *[]){
385 "disp_cc_mdss_byte1_div_clk_src",
388 .flags
= CLK_SET_RATE_PARENT
,
389 .ops
= &clk_branch2_ops
,
394 static struct clk_branch disp_cc_mdss_esc0_clk
= {
396 .halt_check
= BRANCH_HALT
,
398 .enable_reg
= 0x2038,
399 .enable_mask
= BIT(0),
400 .hw
.init
= &(struct clk_init_data
){
401 .name
= "disp_cc_mdss_esc0_clk",
402 .parent_names
= (const char *[]){
403 "disp_cc_mdss_esc0_clk_src",
406 .flags
= CLK_SET_RATE_PARENT
,
407 .ops
= &clk_branch2_ops
,
412 static struct clk_branch disp_cc_mdss_esc1_clk
= {
414 .halt_check
= BRANCH_HALT
,
416 .enable_reg
= 0x203c,
417 .enable_mask
= BIT(0),
418 .hw
.init
= &(struct clk_init_data
){
419 .name
= "disp_cc_mdss_esc1_clk",
420 .parent_names
= (const char *[]){
421 "disp_cc_mdss_esc1_clk_src",
424 .flags
= CLK_SET_RATE_PARENT
,
425 .ops
= &clk_branch2_ops
,
430 static struct clk_branch disp_cc_mdss_mdp_clk
= {
432 .halt_check
= BRANCH_HALT
,
434 .enable_reg
= 0x200c,
435 .enable_mask
= BIT(0),
436 .hw
.init
= &(struct clk_init_data
){
437 .name
= "disp_cc_mdss_mdp_clk",
438 .parent_names
= (const char *[]){
439 "disp_cc_mdss_mdp_clk_src",
442 .flags
= CLK_SET_RATE_PARENT
,
443 .ops
= &clk_branch2_ops
,
448 static struct clk_branch disp_cc_mdss_mdp_lut_clk
= {
450 .halt_check
= BRANCH_HALT
,
452 .enable_reg
= 0x201c,
453 .enable_mask
= BIT(0),
454 .hw
.init
= &(struct clk_init_data
){
455 .name
= "disp_cc_mdss_mdp_lut_clk",
456 .parent_names
= (const char *[]){
457 "disp_cc_mdss_mdp_clk_src",
460 .ops
= &clk_branch2_ops
,
465 /* Return the HW recalc rate for idle use case */
466 static struct clk_branch disp_cc_mdss_pclk0_clk
= {
468 .halt_check
= BRANCH_HALT
,
470 .enable_reg
= 0x2004,
471 .enable_mask
= BIT(0),
472 .hw
.init
= &(struct clk_init_data
){
473 .name
= "disp_cc_mdss_pclk0_clk",
474 .parent_names
= (const char *[]){
475 "disp_cc_mdss_pclk0_clk_src",
478 .flags
= CLK_SET_RATE_PARENT
,
479 .ops
= &clk_branch2_ops
,
484 /* Return the HW recalc rate for idle use case */
485 static struct clk_branch disp_cc_mdss_pclk1_clk
= {
487 .halt_check
= BRANCH_HALT
,
489 .enable_reg
= 0x2008,
490 .enable_mask
= BIT(0),
491 .hw
.init
= &(struct clk_init_data
){
492 .name
= "disp_cc_mdss_pclk1_clk",
493 .parent_names
= (const char *[]){
494 "disp_cc_mdss_pclk1_clk_src",
497 .flags
= CLK_SET_RATE_PARENT
,
498 .ops
= &clk_branch2_ops
,
503 static struct clk_branch disp_cc_mdss_rot_clk
= {
505 .halt_check
= BRANCH_HALT
,
507 .enable_reg
= 0x2014,
508 .enable_mask
= BIT(0),
509 .hw
.init
= &(struct clk_init_data
){
510 .name
= "disp_cc_mdss_rot_clk",
511 .parent_names
= (const char *[]){
512 "disp_cc_mdss_rot_clk_src",
515 .flags
= CLK_SET_RATE_PARENT
,
516 .ops
= &clk_branch2_ops
,
521 static struct clk_branch disp_cc_mdss_rscc_ahb_clk
= {
523 .halt_check
= BRANCH_HALT
,
525 .enable_reg
= 0x5004,
526 .enable_mask
= BIT(0),
527 .hw
.init
= &(struct clk_init_data
){
528 .name
= "disp_cc_mdss_rscc_ahb_clk",
529 .ops
= &clk_branch2_ops
,
534 static struct clk_branch disp_cc_mdss_rscc_vsync_clk
= {
536 .halt_check
= BRANCH_HALT
,
538 .enable_reg
= 0x5008,
539 .enable_mask
= BIT(0),
540 .hw
.init
= &(struct clk_init_data
){
541 .name
= "disp_cc_mdss_rscc_vsync_clk",
542 .parent_names
= (const char *[]){
543 "disp_cc_mdss_vsync_clk_src",
546 .flags
= CLK_SET_RATE_PARENT
,
547 .ops
= &clk_branch2_ops
,
552 static struct clk_branch disp_cc_mdss_vsync_clk
= {
554 .halt_check
= BRANCH_HALT
,
556 .enable_reg
= 0x2024,
557 .enable_mask
= BIT(0),
558 .hw
.init
= &(struct clk_init_data
){
559 .name
= "disp_cc_mdss_vsync_clk",
560 .parent_names
= (const char *[]){
561 "disp_cc_mdss_vsync_clk_src",
564 .flags
= CLK_SET_RATE_PARENT
,
565 .ops
= &clk_branch2_ops
,
570 static struct gdsc mdss_gdsc
= {
575 .pwrsts
= PWRSTS_OFF_ON
,
576 .flags
= HW_CTRL
| POLL_CFG_GDSCR
,
579 static struct clk_regmap
*disp_cc_sdm845_clocks
[] = {
580 [DISP_CC_MDSS_AHB_CLK
] = &disp_cc_mdss_ahb_clk
.clkr
,
581 [DISP_CC_MDSS_AXI_CLK
] = &disp_cc_mdss_axi_clk
.clkr
,
582 [DISP_CC_MDSS_BYTE0_CLK
] = &disp_cc_mdss_byte0_clk
.clkr
,
583 [DISP_CC_MDSS_BYTE0_CLK_SRC
] = &disp_cc_mdss_byte0_clk_src
.clkr
,
584 [DISP_CC_MDSS_BYTE0_INTF_CLK
] = &disp_cc_mdss_byte0_intf_clk
.clkr
,
585 [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC
] =
586 &disp_cc_mdss_byte0_div_clk_src
.clkr
,
587 [DISP_CC_MDSS_BYTE1_CLK
] = &disp_cc_mdss_byte1_clk
.clkr
,
588 [DISP_CC_MDSS_BYTE1_CLK_SRC
] = &disp_cc_mdss_byte1_clk_src
.clkr
,
589 [DISP_CC_MDSS_BYTE1_INTF_CLK
] = &disp_cc_mdss_byte1_intf_clk
.clkr
,
590 [DISP_CC_MDSS_BYTE1_DIV_CLK_SRC
] =
591 &disp_cc_mdss_byte1_div_clk_src
.clkr
,
592 [DISP_CC_MDSS_ESC0_CLK
] = &disp_cc_mdss_esc0_clk
.clkr
,
593 [DISP_CC_MDSS_ESC0_CLK_SRC
] = &disp_cc_mdss_esc0_clk_src
.clkr
,
594 [DISP_CC_MDSS_ESC1_CLK
] = &disp_cc_mdss_esc1_clk
.clkr
,
595 [DISP_CC_MDSS_ESC1_CLK_SRC
] = &disp_cc_mdss_esc1_clk_src
.clkr
,
596 [DISP_CC_MDSS_MDP_CLK
] = &disp_cc_mdss_mdp_clk
.clkr
,
597 [DISP_CC_MDSS_MDP_CLK_SRC
] = &disp_cc_mdss_mdp_clk_src
.clkr
,
598 [DISP_CC_MDSS_MDP_LUT_CLK
] = &disp_cc_mdss_mdp_lut_clk
.clkr
,
599 [DISP_CC_MDSS_PCLK0_CLK
] = &disp_cc_mdss_pclk0_clk
.clkr
,
600 [DISP_CC_MDSS_PCLK0_CLK_SRC
] = &disp_cc_mdss_pclk0_clk_src
.clkr
,
601 [DISP_CC_MDSS_PCLK1_CLK
] = &disp_cc_mdss_pclk1_clk
.clkr
,
602 [DISP_CC_MDSS_PCLK1_CLK_SRC
] = &disp_cc_mdss_pclk1_clk_src
.clkr
,
603 [DISP_CC_MDSS_ROT_CLK
] = &disp_cc_mdss_rot_clk
.clkr
,
604 [DISP_CC_MDSS_ROT_CLK_SRC
] = &disp_cc_mdss_rot_clk_src
.clkr
,
605 [DISP_CC_MDSS_RSCC_AHB_CLK
] = &disp_cc_mdss_rscc_ahb_clk
.clkr
,
606 [DISP_CC_MDSS_RSCC_VSYNC_CLK
] = &disp_cc_mdss_rscc_vsync_clk
.clkr
,
607 [DISP_CC_MDSS_VSYNC_CLK
] = &disp_cc_mdss_vsync_clk
.clkr
,
608 [DISP_CC_MDSS_VSYNC_CLK_SRC
] = &disp_cc_mdss_vsync_clk_src
.clkr
,
609 [DISP_CC_PLL0
] = &disp_cc_pll0
.clkr
,
612 static const struct qcom_reset_map disp_cc_sdm845_resets
[] = {
613 [DISP_CC_MDSS_RSCC_BCR
] = { 0x5000 },
616 static struct gdsc
*disp_cc_sdm845_gdscs
[] = {
617 [MDSS_GDSC
] = &mdss_gdsc
,
620 static const struct regmap_config disp_cc_sdm845_regmap_config
= {
624 .max_register
= 0x10000,
628 static const struct qcom_cc_desc disp_cc_sdm845_desc
= {
629 .config
= &disp_cc_sdm845_regmap_config
,
630 .clks
= disp_cc_sdm845_clocks
,
631 .num_clks
= ARRAY_SIZE(disp_cc_sdm845_clocks
),
632 .resets
= disp_cc_sdm845_resets
,
633 .num_resets
= ARRAY_SIZE(disp_cc_sdm845_resets
),
634 .gdscs
= disp_cc_sdm845_gdscs
,
635 .num_gdscs
= ARRAY_SIZE(disp_cc_sdm845_gdscs
),
638 static const struct of_device_id disp_cc_sdm845_match_table
[] = {
639 { .compatible
= "qcom,sdm845-dispcc" },
642 MODULE_DEVICE_TABLE(of
, disp_cc_sdm845_match_table
);
644 static int disp_cc_sdm845_probe(struct platform_device
*pdev
)
646 struct regmap
*regmap
;
647 struct alpha_pll_config disp_cc_pll0_config
= {};
649 regmap
= qcom_cc_map(pdev
, &disp_cc_sdm845_desc
);
651 return PTR_ERR(regmap
);
653 disp_cc_pll0_config
.l
= 0x2c;
654 disp_cc_pll0_config
.alpha
= 0xcaaa;
656 clk_fabia_pll_configure(&disp_cc_pll0
, regmap
, &disp_cc_pll0_config
);
658 /* Enable hardware clock gating for DSI and MDP clocks */
659 regmap_update_bits(regmap
, 0x8000, 0x7f0, 0x7f0);
661 return qcom_cc_really_probe(pdev
, &disp_cc_sdm845_desc
, regmap
);
664 static struct platform_driver disp_cc_sdm845_driver
= {
665 .probe
= disp_cc_sdm845_probe
,
667 .name
= "disp_cc-sdm845",
668 .of_match_table
= disp_cc_sdm845_match_table
,
672 static int __init
disp_cc_sdm845_init(void)
674 return platform_driver_register(&disp_cc_sdm845_driver
);
676 subsys_initcall(disp_cc_sdm845_init
);
678 static void __exit
disp_cc_sdm845_exit(void)
680 platform_driver_unregister(&disp_cc_sdm845_driver
);
682 module_exit(disp_cc_sdm845_exit
);
684 MODULE_LICENSE("GPL v2");
685 MODULE_DESCRIPTION("QTI DISPCC SDM845 Driver");