blob: 9694959dd5ed3cd22f5cc00dc4edb451ce2d158a
1 | /* |
2 | * drivers/amlogic/media/common/arch/clk/clkgx.c |
3 | * |
4 | * Copyright (C) 2016 Amlogic, Inc. All rights reserved. |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, but WITHOUT |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
14 | * more details. |
15 | * |
16 | */ |
17 | #define DEBUG |
18 | #include <linux/init.h> |
19 | #include <linux/kernel.h> |
20 | #include <linux/types.h> |
21 | #include <linux/clk.h> |
22 | #include <linux/delay.h> |
23 | #include <linux/amlogic/media/clk/gp_pll.h> |
24 | #include <linux/amlogic/media/utils/vdec_reg.h> |
25 | #include <linux/amlogic/media/utils/amports_config.h> |
26 | #include "../../../frame_provider/decoder/utils/vdec.h" |
27 | #include <linux/amlogic/media/registers/register.h> |
28 | #include "clk_priv.h" |
29 | #include <linux/amlogic/media/utils/log.h> |
30 | |
31 | #include <linux/amlogic/media/registers/register_ops.h> |
32 | #include "../switch/amports_gate.h" |
33 | #include "../../chips/decoder_cpu_ver_info.h" |
34 | |
35 | #define MHz (1000000) |
36 | #define debug_print pr_info |
37 | #define TL1_HEVC_MAX_CLK (800) |
38 | |
39 | //#define NO_CLKTREE |
40 | |
41 | /* set gp0 648M vdec use gp0 clk*/ |
42 | #define VDEC1_648M() \ |
43 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (0), 0, 16) |
44 | |
45 | #define HEVC_648M() \ |
46 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (0), 16, 16) |
47 | |
48 | /*set gp0 1296M vdec use gp0 clk div2*/ |
49 | #define VDEC1_648M_DIV() \ |
50 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (1), 0, 16) |
51 | |
52 | #define HEVC_648M_DIV() \ |
53 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (1), 16, 16) |
54 | |
55 | #define VDEC1_WITH_GP_PLL() \ |
56 | ((READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0xe00) == 0xc00) |
57 | #define HEVC_WITH_GP_PLL() \ |
58 | ((READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0xe000000) == 0xc000000) |
59 | |
60 | #define VDEC1_CLOCK_ON() \ |
61 | do { if (is_meson_m8_cpu()) { \ |
62 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \ |
63 | WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \ |
64 | } else { \ |
65 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \ |
66 | WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 15, 1); \ |
67 | WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 8, 1); \ |
68 | WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \ |
69 | } \ |
70 | } while (0) |
71 | |
72 | #define VDEC2_CLOCK_ON() do {\ |
73 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \ |
74 | WRITE_VREG(DOS_GCLK_EN1, 0x3ff);\ |
75 | } while (0) |
76 | |
77 | #define HCODEC_CLOCK_ON() do {\ |
78 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 24, 1); \ |
79 | WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15);\ |
80 | } while (0) |
81 | #define HEVC_CLOCK_ON() do {\ |
82 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 24, 1); \ |
83 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \ |
84 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 31, 1); \ |
85 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 15, 1); \ |
86 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 24, 1); \ |
87 | WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);\ |
88 | } while (0) |
89 | #define VDEC1_SAFE_CLOCK() do {\ |
90 | WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, \ |
91 | READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x7f, 0, 7); \ |
92 | WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 8, 1); \ |
93 | WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 15, 1);\ |
94 | } while (0) |
95 | |
96 | #define VDEC1_CLOCK_OFF() \ |
97 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 8, 1) |
98 | #define VDEC2_CLOCK_OFF() \ |
99 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1) |
100 | #define HCODEC_CLOCK_OFF() \ |
101 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 24, 1) |
102 | #define HEVC_SAFE_CLOCK() do { \ |
103 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \ |
104 | (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 16) & 0x7f, 16, 7);\ |
105 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \ |
106 | (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 25) & 0x7f, 25, 7);\ |
107 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 24, 1); \ |
108 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 31, 1);\ |
109 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 15, 1);\ |
110 | } while (0) |
111 | |
112 | #define HEVC_CLOCK_OFF() do {\ |
113 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 24, 1);\ |
114 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1);\ |
115 | }while(0) |
116 | |
117 | static int clock_real_clk[VDEC_MAX + 1]; |
118 | |
119 | static unsigned int set_frq_enable, vdec_frq, hevc_frq, hevcb_frq; |
120 | |
121 | #ifdef NO_CLKTREE |
122 | static struct gp_pll_user_handle_s *gp_pll_user_vdec, *gp_pll_user_hevc; |
123 | static bool is_gp0_div2 = true; |
124 | |
125 | static int gp_pll_user_cb_vdec(struct gp_pll_user_handle_s *user, |
126 | int event) |
127 | { |
128 | debug_print("gp_pll_user_cb_vdec call\n"); |
129 | if (event == GP_PLL_USER_EVENT_GRANT) { |
130 | struct clk *clk = clk_get(NULL, "gp0_pll"); |
131 | if (!IS_ERR(clk)) { |
132 | if (is_gp0_div2) |
133 | clk_set_rate(clk, 1296000000UL); |
134 | else |
135 | clk_set_rate(clk, 648000000UL); |
136 | VDEC1_SAFE_CLOCK(); |
137 | VDEC1_CLOCK_OFF(); |
138 | if (is_gp0_div2) |
139 | VDEC1_648M_DIV(); |
140 | else |
141 | VDEC1_648M(); |
142 | |
143 | VDEC1_CLOCK_ON(); |
144 | debug_print("gp_pll_user_cb_vdec call set\n"); |
145 | } |
146 | } |
147 | return 0; |
148 | } |
149 | |
150 | static int gp_pll_user_cb_hevc(struct gp_pll_user_handle_s *user, |
151 | int event) |
152 | { |
153 | debug_print("gp_pll_user_cb_hevc callback\n"); |
154 | if (event == GP_PLL_USER_EVENT_GRANT) { |
155 | struct clk *clk = clk_get(NULL, "gp0_pll"); |
156 | if (!IS_ERR(clk)) { |
157 | if (is_gp0_div2) |
158 | clk_set_rate(clk, 1296000000UL); |
159 | else |
160 | clk_set_rate(clk, 648000000UL); |
161 | // HEVC_SAFE_CLOCK(); |
162 | HEVC_CLOCK_OFF(); |
163 | if (is_gp0_div2) |
164 | HEVC_648M_DIV(); |
165 | else |
166 | HEVC_648M(); |
167 | HEVC_CLOCK_ON(); |
168 | debug_print("gp_pll_user_cb_hevc callback2\n"); |
169 | } |
170 | } |
171 | |
172 | return 0; |
173 | } |
174 | |
175 | |
176 | #endif |
177 | |
178 | struct clk_mux_s { |
179 | struct gate_switch_node *vdec_mux_node; |
180 | struct gate_switch_node *hcodec_mux_node; |
181 | struct gate_switch_node *hevc_mux_node; |
182 | struct gate_switch_node *hevc_back_mux_node; |
183 | }; |
184 | |
185 | struct clk_mux_s gclk; |
186 | |
187 | void vdec1_set_clk(int source, int div) |
188 | { |
189 | pr_debug("vdec1_set_clk %d, %d\n", source, div); |
190 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (source << 9) | (div - 1), 0, 16); |
191 | } |
192 | EXPORT_SYMBOL(vdec1_set_clk); |
193 | |
194 | void hcodec_set_clk(int source, int div) |
195 | { |
196 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, |
197 | (source << 9) | (div - 1), 16, 16); |
198 | } |
199 | EXPORT_SYMBOL(hcodec_set_clk); |
200 | |
201 | void vdec2_set_clk(int source, int div) |
202 | { |
203 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, |
204 | (source << 9) | (div - 1), 0, 16); |
205 | } |
206 | EXPORT_SYMBOL(vdec2_set_clk); |
207 | |
208 | //extern uint force_hevc_clock_cntl; |
209 | uint force_hevc_clock_cntl = 0; |
210 | void hevc_set_clk(int source, int div) |
211 | { |
212 | if (force_hevc_clock_cntl) { |
213 | pr_info("%s, write force clock cntl %x\n", __func__, force_hevc_clock_cntl); |
214 | WRITE_HHI_REG(HHI_VDEC2_CLK_CNTL, force_hevc_clock_cntl); |
215 | } else { |
216 | pr_debug("hevc_set_clk %d, %d\n", source, div); |
217 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, |
218 | (source << 9) | (div - 1), 16, 16); |
219 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (source << 9) | (div - 1), 0, 16); |
220 | } |
221 | } |
222 | EXPORT_SYMBOL(hevc_set_clk); |
223 | |
224 | void vdec_get_clk_source(int clk, int *source, int *div, int *rclk) |
225 | { |
226 | #define source_div4 (0) |
227 | #define source_div3 (1) |
228 | #define source_div5 (2) |
229 | #define source_div7 (3) |
230 | if (clk > 500) { |
231 | *source = source_div3; |
232 | *div = 1; |
233 | *rclk = 667; |
234 | } else if (clk >= 500) { |
235 | *source = source_div4; |
236 | *div = 1; |
237 | *rclk = 500; |
238 | } else if (clk >= 400) { |
239 | *source = source_div5; |
240 | *div = 1; |
241 | *rclk = 400; |
242 | } else if (clk >= 333) { |
243 | *source = source_div3; |
244 | *div = 2; |
245 | *rclk = 333; |
246 | } else if (clk >= 200) { |
247 | *source = source_div5; |
248 | *div = 2; |
249 | *rclk = 200; |
250 | } else if (clk >= 166) { |
251 | *source = source_div4; |
252 | *div = 3; |
253 | *rclk = 166; |
254 | } else if (clk >= 133) { |
255 | *source = source_div5; |
256 | *div = 3; |
257 | *rclk = 133; |
258 | } else if (clk >= 100) { |
259 | *source = source_div5; |
260 | *div = 4; |
261 | *rclk = 100; |
262 | } else if (clk >= 50) { |
263 | *source = source_div5; |
264 | *div = 8; |
265 | *rclk = 50; |
266 | } else { |
267 | *source = source_div5; |
268 | *div = 20; |
269 | *rclk = 10; |
270 | } |
271 | } |
272 | EXPORT_SYMBOL(vdec_get_clk_source); |
273 | |
274 | |
275 | /* |
276 | *enum vformat_e { |
277 | * VFORMAT_MPEG12 = 0, |
278 | * VFORMAT_MPEG4, |
279 | * VFORMAT_H264, |
280 | * VFORMAT_MJPEG, |
281 | * VFORMAT_REAL, |
282 | * VFORMAT_JPEG, |
283 | * VFORMAT_VC1, |
284 | * VFORMAT_AVS, |
285 | * VFORMAT_YUV, |
286 | * VFORMAT_H264MVC, |
287 | * VFORMAT_H264_4K2K, |
288 | * VFORMAT_HEVC, |
289 | * VFORMAT_H264_ENC, |
290 | * VFORMAT_JPEG_ENC, |
291 | * VFORMAT_VP9, |
292 | * VFORMAT_MAX |
293 | *}; |
294 | *sample: |
295 | *{{1280*720*30, 100}, {1920*1080*30, 166}, {1920*1080*60, 333}, |
296 | * {4096*2048*30, 600}, {4096*2048*60, 600}, {INT_MAX, 600},} |
297 | *mean: |
298 | *width * height * fps |
299 | *<720p30fps clk=100MHZ |
300 | *>=720p30fps & < 1080p30fps clk=166MHZ |
301 | *>=1080p 30fps & < 1080p60fps clk=333MHZ |
302 | */ |
303 | static struct clk_set_setting clks_for_formats[] = { |
304 | { /*[VFORMAT_MPEG12] */ |
305 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, |
306 | {1920 * 1080 * 60, 333}, |
307 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
308 | 600}, {INT_MAX, 600}, |
309 | } |
310 | }, |
311 | { /*[VFORMAT_MPEG4] */ |
312 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, |
313 | {1920 * 1080 * 60, 333}, |
314 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
315 | 600}, {INT_MAX, 600}, |
316 | } |
317 | }, |
318 | { /*[VFORMAT_H264] */ |
319 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 21, 166}, |
320 | {1920 * 1080 * 30, 333}, |
321 | {1920 * 1080 * 60, 600}, {4096 * 2048 * 60, |
322 | 600}, {INT_MAX, 600}, |
323 | } |
324 | }, |
325 | { /*[VFORMAT_MJPEG] */ |
326 | {{1280 * 720 * 30, 200}, {1920 * 1080 * 30, 200}, |
327 | {1920 * 1080 * 60, 333}, |
328 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
329 | 600}, {INT_MAX, 600}, |
330 | } |
331 | }, |
332 | { /*[VFORMAT_REAL] */ |
333 | {{1280 * 720 * 20, 200}, {1920 * 1080 * 30, 500}, |
334 | {1920 * 1080 * 60, 500}, |
335 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
336 | 600}, {INT_MAX, 600}, |
337 | } |
338 | }, |
339 | { /*[VFORMAT_JPEG] */ |
340 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, |
341 | {1920 * 1080 * 60, 333}, |
342 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
343 | 600}, {INT_MAX, 600}, |
344 | } |
345 | }, |
346 | { /*[VFORMAT_VC1] */ |
347 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, |
348 | {1920 * 1080 * 60, 333}, |
349 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
350 | 600}, {INT_MAX, 600}, |
351 | } |
352 | }, |
353 | { /*[VFORMAT_AVS] */ |
354 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, |
355 | {1920 * 1080 * 60, 333}, |
356 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
357 | 600}, {INT_MAX, 600}, |
358 | } |
359 | }, |
360 | { /*[VFORMAT_YUV] */ |
361 | {{1280 * 720 * 30, 100}, {INT_MAX, 100}, |
362 | {0, 0}, {0, 0}, {0, 0}, {0, 0}, |
363 | } |
364 | }, |
365 | { /*VFORMAT_H264MVC */ |
366 | {{1280 * 720 * 30, 333}, {1920 * 1080 * 30, 333}, |
367 | {4096 * 2048 * 60, 600}, |
368 | {INT_MAX, 630}, {0, 0}, {0, 0}, |
369 | } |
370 | }, |
371 | { /*VFORMAT_H264_4K2K */ |
372 | {{1280 * 720 * 30, 600}, {4096 * 2048 * 60, 630}, |
373 | {INT_MAX, 630}, |
374 | {0, 0}, {0, 0}, {0, 0}, |
375 | } |
376 | }, |
377 | { /*VFORMAT_HEVC */ |
378 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 60, 600}, |
379 | {4096 * 2048 * 25, 630}, |
380 | {4096 * 2048 * 30, 630}, {4096 * 2048 * 60, |
381 | 630}, {INT_MAX, 630}, |
382 | } |
383 | }, |
384 | { /*VFORMAT_H264_ENC */ |
385 | {{1280 * 720 * 30, 0}, {INT_MAX, 0}, |
386 | {0, 0}, {0, 0}, {0, 0}, {0, 0}, |
387 | } |
388 | }, |
389 | { /*VFORMAT_JPEG_ENC */ |
390 | {{1280 * 720 * 30, 0}, {INT_MAX, 0}, |
391 | {0, 0}, {0, 0}, {0, 0}, {0, 0}, |
392 | } |
393 | }, |
394 | { /*VFORMAT_VP9 */ |
395 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 100}, |
396 | {1920 * 1080 * 60, 166}, |
397 | {4096 * 2048 * 30, 333}, {4096 * 2048 * 60, |
398 | 630}, {INT_MAX, 630}, |
399 | } |
400 | }, |
401 | {/*VFORMAT_AVS2*/ |
402 | {{1280*720*30, 100}, {1920*1080*30, 100}, |
403 | {1920*1080*60, 166}, {4096*2048*30, 333}, |
404 | {4096*2048*60, 630}, {INT_MAX, 630},} |
405 | }, |
406 | {/*VFORMAT_AV1*/ |
407 | {{1280*720*30, 100}, {1920*1080*30, 100}, |
408 | {1920*1080*60, 166}, {4096*2048*30, 333}, |
409 | {4096*2048*60, 630}, {INT_MAX, 630},} |
410 | }, |
411 | |
412 | }; |
413 | |
414 | void set_clock_gate(struct gate_switch_node *nodes, int num) |
415 | { |
416 | struct gate_switch_node *node = NULL; |
417 | |
418 | do { |
419 | node = &nodes[num - 1]; |
420 | if (IS_ERR_OR_NULL(node)) |
421 | pr_info("get mux clk err.\n"); |
422 | |
423 | if (!strcmp(node->name, "clk_vdec_mux")) |
424 | gclk.vdec_mux_node = node; |
425 | else if (!strcmp(node->name, "clk_hcodec_mux")) |
426 | gclk.hcodec_mux_node = node; |
427 | else if (!strcmp(node->name, "clk_hevc_mux")) |
428 | gclk.hevc_mux_node = node; |
429 | else if (!strcmp(node->name, "clk_hevcb_mux")) |
430 | gclk.hevc_back_mux_node = node; |
431 | } while(--num); |
432 | } |
433 | EXPORT_SYMBOL(set_clock_gate); |
434 | #ifdef NO_CLKTREE |
435 | int vdec_set_clk(int dec, int source, int div) |
436 | { |
437 | |
438 | if (dec == VDEC_1) |
439 | vdec1_set_clk(source, div); |
440 | else if (dec == VDEC_2) |
441 | vdec2_set_clk(source, div); |
442 | else if (dec == VDEC_HEVC) |
443 | hevc_set_clk(source, div); |
444 | else if (dec == VDEC_HCODEC) |
445 | hcodec_set_clk(source, div); |
446 | return 0; |
447 | } |
448 | |
449 | #else |
450 | static int vdec_set_clk(int dec, int rate) |
451 | { |
452 | struct clk *clk = NULL; |
453 | |
454 | switch (dec) { |
455 | case VDEC_1: |
456 | clk = gclk.vdec_mux_node->clk; |
457 | WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); |
458 | break; |
459 | |
460 | case VDEC_HCODEC: |
461 | clk = gclk.hcodec_mux_node->clk; |
462 | WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15); |
463 | break; |
464 | |
465 | case VDEC_2: |
466 | clk = gclk.vdec_mux_node->clk; |
467 | WRITE_VREG(DOS_GCLK_EN1, 0x3ff); |
468 | break; |
469 | |
470 | case VDEC_HEVC: |
471 | clk = gclk.hevc_mux_node->clk; |
472 | WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); |
473 | break; |
474 | |
475 | case VDEC_HEVCB: |
476 | clk = gclk.hevc_back_mux_node->clk; |
477 | WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); |
478 | break; |
479 | |
480 | case VDEC_MAX: |
481 | break; |
482 | |
483 | default: |
484 | pr_info("invaild vdec type.\n"); |
485 | } |
486 | |
487 | if (IS_ERR_OR_NULL(clk)) { |
488 | pr_info("the mux clk err.\n"); |
489 | return -1; |
490 | } |
491 | |
492 | clk_set_rate(clk, rate); |
493 | |
494 | return 0; |
495 | } |
496 | |
497 | static int vdec_clock_init(void) |
498 | { |
499 | return 0; |
500 | } |
501 | |
502 | #endif |
503 | #ifdef NO_CLKTREE |
504 | static int vdec_clock_init(void) |
505 | { |
506 | gp_pll_user_vdec = gp_pll_user_register("vdec", 0, |
507 | gp_pll_user_cb_vdec); |
508 | if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL) |
509 | is_gp0_div2 = false; |
510 | else |
511 | is_gp0_div2 = true; |
512 | |
513 | if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_GXL) { |
514 | pr_info("used fix clk for vdec clk source!\n"); |
515 | //update_vdec_clk_config_settings(1); |
516 | } |
517 | return (gp_pll_user_vdec) ? 0 : -ENOMEM; |
518 | } |
519 | |
520 | |
521 | |
522 | static void update_clk_with_clk_configs( |
523 | int clk, int *source, int *div, int *rclk) |
524 | { |
525 | unsigned int config = 0;//get_vdec_clk_config_settings(); |
526 | |
527 | if (!config) |
528 | return; |
529 | if (config >= 10) { |
530 | int wantclk; |
531 | wantclk = config; |
532 | vdec_get_clk_source(wantclk, source, div, rclk); |
533 | } |
534 | return; |
535 | } |
536 | #define NO_GP0_PLL 0//(get_vdec_clk_config_settings() == 1) |
537 | #define ALWAYS_GP0_PLL 0//(get_vdec_clk_config_settings() == 2) |
538 | |
539 | #define NO_GP0_PLL 0//(get_vdec_clk_config_settings() == 1) |
540 | #define ALWAYS_GP0_PLL 0//(get_vdec_clk_config_settings() == 2) |
541 | |
542 | static int vdec_clock_set(int clk) |
543 | { |
544 | int use_gpll = 0; |
545 | int source, div, rclk; |
546 | int clk_seted = 0; |
547 | int gp_pll_wait = 0; |
548 | if (clk == 1) |
549 | clk = 200; |
550 | else if (clk == 2) { |
551 | if (clock_real_clk[VDEC_1] != 648) |
552 | clk = 500; |
553 | else |
554 | clk = 648; |
555 | } else if (clk == 0) { |
556 | /*used for release gp pull. |
557 | if used, release it. |
558 | if not used gp pll |
559 | do nothing. |
560 | */ |
561 | if (clock_real_clk[VDEC_1] == 667 || |
562 | (clock_real_clk[VDEC_1] == 648) || |
563 | clock_real_clk[VDEC_1] <= 0) |
564 | clk = 200; |
565 | else |
566 | clk = clock_real_clk[VDEC_1]; |
567 | } |
568 | vdec_get_clk_source(clk, &source, &div, &rclk); |
569 | update_clk_with_clk_configs(clk, &source, &div, &rclk); |
570 | |
571 | if (clock_real_clk[VDEC_1] == rclk) |
572 | return rclk; |
573 | if (NO_GP0_PLL) { |
574 | use_gpll = 0; |
575 | clk_seted = 0; |
576 | } else if ((rclk > 500 && clk != 667) || ALWAYS_GP0_PLL) { |
577 | if (clock_real_clk[VDEC_1] == 648) |
578 | return 648; |
579 | use_gpll = 1; |
580 | gp_pll_request(gp_pll_user_vdec); |
581 | while (!VDEC1_WITH_GP_PLL() && gp_pll_wait++ < 1000000) |
582 | udelay(1); |
583 | if (VDEC1_WITH_GP_PLL()) { |
584 | clk_seted = 1; |
585 | rclk = 648; |
586 | } else { |
587 | use_gpll = 0; |
588 | rclk = 667; |
589 | /*gp_pull request failed,used default 500Mhz*/ |
590 | pr_info("get gp pll failed used fix pull\n"); |
591 | } |
592 | } |
593 | if (!clk_seted) {/*if 648 not set,*/ |
594 | VDEC1_SAFE_CLOCK(); |
595 | VDEC1_CLOCK_OFF(); |
596 | vdec_set_clk(VDEC_1, source, div); |
597 | VDEC1_CLOCK_ON(); |
598 | } |
599 | |
600 | if (!use_gpll) |
601 | gp_pll_release(gp_pll_user_vdec); |
602 | clock_real_clk[VDEC_1] = rclk; |
603 | debug_print("vdec_clock_set 2 to %d\n", rclk); |
604 | return rclk; |
605 | } |
606 | static int hevc_clock_init(void) |
607 | { |
608 | gp_pll_user_hevc = gp_pll_user_register("hevc", 0, |
609 | gp_pll_user_cb_hevc); |
610 | |
611 | return (gp_pll_user_hevc) ? 0 : -ENOMEM; |
612 | } |
613 | static int hevc_back_clock_init(void) |
614 | { |
615 | return 0; |
616 | } |
617 | |
618 | static int hevc_back_clock_set(int clk) |
619 | { |
620 | return 0; |
621 | } |
622 | |
623 | static int hevc_clock_set(int clk) |
624 | { |
625 | int use_gpll = 0; |
626 | int source, div, rclk; |
627 | int gp_pll_wait = 0; |
628 | int clk_seted = 0; |
629 | |
630 | debug_print("hevc_clock_set 1 to clk %d\n", clk); |
631 | if (clk == 1) |
632 | clk = 200; |
633 | else if (clk == 2) { |
634 | if (clock_real_clk[VDEC_HEVC] != 648) |
635 | clk = 500; |
636 | else |
637 | clk = 648; |
638 | } else if (clk == 0) { |
639 | /*used for release gp pull. |
640 | if used, release it. |
641 | if not used gp pll |
642 | do nothing. |
643 | */ |
644 | if ((clock_real_clk[VDEC_HEVC] == 667) || |
645 | (clock_real_clk[VDEC_HEVC] == 648) || |
646 | (clock_real_clk[VDEC_HEVC] <= 0)) |
647 | clk = 200; |
648 | else |
649 | clk = clock_real_clk[VDEC_HEVC]; |
650 | } |
651 | vdec_get_clk_source(clk, &source, &div, &rclk); |
652 | update_clk_with_clk_configs(clk, &source, &div, &rclk); |
653 | |
654 | if (rclk == clock_real_clk[VDEC_HEVC]) |
655 | return rclk;/*clk not changed,*/ |
656 | if (NO_GP0_PLL) { |
657 | use_gpll = 0; |
658 | clk_seted = 0; |
659 | } else if ((rclk > 500 && clk != 667) || ALWAYS_GP0_PLL) { |
660 | if (clock_real_clk[VDEC_HEVC] == 648) |
661 | return 648; |
662 | use_gpll = 1; |
663 | gp_pll_request(gp_pll_user_hevc); |
664 | while (!HEVC_WITH_GP_PLL() && gp_pll_wait++ < 1000000) |
665 | udelay(1); |
666 | if (HEVC_WITH_GP_PLL()) { |
667 | clk_seted = 1; |
668 | rclk = 648; |
669 | } else { |
670 | rclk = 667; |
671 | /*gp_pull request failed,used default 500Mhz*/ |
672 | pr_info("get gp pll failed used fix pull\n"); |
673 | } |
674 | } |
675 | if (!clk_seted) {/*if 648 not set,*/ |
676 | // HEVC_SAFE_CLOCK(); |
677 | HEVC_CLOCK_OFF(); |
678 | vdec_set_clk(VDEC_HEVC, source, div); |
679 | HEVC_CLOCK_ON(); |
680 | } |
681 | if (!use_gpll) |
682 | gp_pll_release(gp_pll_user_hevc); |
683 | clock_real_clk[VDEC_HEVC] = rclk; |
684 | /*debug_print("hevc_clock_set 2 to rclk=%d, configs=%d\n", |
685 | rclk, |
686 | get_vdec_clk_config_settings());*/ //DEBUG_TMP |
687 | return rclk; |
688 | } |
689 | |
690 | static int hcodec_clock_set(int clk) |
691 | { |
692 | int source, div, rclk; |
693 | HCODEC_CLOCK_OFF(); |
694 | vdec_get_clk_source(200, &source, &div, &rclk); |
695 | vdec_set_clk(VDEC_HCODEC, source, div); |
696 | HCODEC_CLOCK_ON(); |
697 | clock_real_clk[VDEC_HCODEC] = rclk; |
698 | return rclk; |
699 | } |
700 | |
701 | |
702 | #else |
703 | static int vdec_clock_set(int clk) |
704 | { |
705 | if (clk == 1) |
706 | clk = 200; |
707 | else if (clk == 2) { |
708 | if (clock_real_clk[VDEC_1] != 648) |
709 | clk = 500; |
710 | else |
711 | clk = 648; |
712 | } else if (clk == 0) { |
713 | if (clock_real_clk[VDEC_1] == 667 || |
714 | (clock_real_clk[VDEC_1] == 648) || |
715 | clock_real_clk[VDEC_1] <= 0) |
716 | clk = 200; |
717 | else |
718 | clk = clock_real_clk[VDEC_1]; |
719 | } |
720 | |
721 | if ((clk > 500 && clk != 667)) { |
722 | if (clock_real_clk[VDEC_1] == 648) |
723 | return 648; |
724 | clk = 667; |
725 | } |
726 | |
727 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1 && |
728 | get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_TL1) |
729 | clk = 800; |
730 | |
731 | if (set_frq_enable && vdec_frq) { |
732 | pr_info("Set the vdec frq is %u MHz\n", vdec_frq); |
733 | clk = vdec_frq; |
734 | } |
735 | |
736 | vdec_set_clk(VDEC_1, clk * MHz); |
737 | |
738 | clock_real_clk[VDEC_1] = clk; |
739 | |
740 | pr_debug("vdec mux clock is %lu Hz\n", |
741 | clk_get_rate(gclk.vdec_mux_node->clk)); |
742 | |
743 | return clk; |
744 | } |
745 | |
746 | static int hevc_clock_init(void) |
747 | { |
748 | return 0; |
749 | } |
750 | |
751 | static int hevc_back_clock_init(void) |
752 | { |
753 | return 0; |
754 | } |
755 | |
756 | static int hevc_back_clock_set(int clk) |
757 | { |
758 | if (clk == 1) |
759 | clk = 200; |
760 | else if (clk == 2) { |
761 | if (clock_real_clk[VDEC_HEVCB] != 648) |
762 | clk = 500; |
763 | else |
764 | clk = 648; |
765 | } else if (clk == 0) { |
766 | if (clock_real_clk[VDEC_HEVCB] == 667 || |
767 | (clock_real_clk[VDEC_HEVCB] == 648) || |
768 | clock_real_clk[VDEC_HEVCB] <= 0) |
769 | clk = 200; |
770 | else |
771 | clk = clock_real_clk[VDEC_HEVCB]; |
772 | } |
773 | |
774 | if ((clk > 500 && clk != 667)) { |
775 | if (clock_real_clk[VDEC_HEVCB] == 648) |
776 | return 648; |
777 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) |
778 | clk = TL1_HEVC_MAX_CLK; |
779 | else |
780 | clk = 667; |
781 | } |
782 | |
783 | if (set_frq_enable && hevcb_frq) { |
784 | pr_info("Set the hevcb frq is %u MHz\n", hevcb_frq); |
785 | clk = hevcb_frq; |
786 | } |
787 | |
788 | if (get_cpu_major_id() >= MESON_CPU_MAJOR_ID_TXLX) { |
789 | if ((READ_EFUSE_REG(EFUSE_LIC1) >> 28 & 0x1) && clk > 333) { |
790 | pr_info("The hevcb clock limit to 333MHz.\n"); |
791 | clk = 333; |
792 | } |
793 | } |
794 | |
795 | vdec_set_clk(VDEC_HEVCB, clk * MHz); |
796 | |
797 | clock_real_clk[VDEC_HEVCB] = clk; |
798 | pr_debug("hevc back mux clock is %lu Hz\n", |
799 | clk_get_rate(gclk.hevc_back_mux_node->clk)); |
800 | |
801 | return clk; |
802 | } |
803 | |
804 | static int hevc_clock_set(int clk) |
805 | { |
806 | if (clk == 1) |
807 | clk = 200; |
808 | else if (clk == 2) { |
809 | if (clock_real_clk[VDEC_HEVC] != 648) |
810 | clk = 500; |
811 | else |
812 | clk = 648; |
813 | } else if (clk == 0) { |
814 | if (clock_real_clk[VDEC_HEVC] == 667 || |
815 | (clock_real_clk[VDEC_HEVC] == 648) || |
816 | clock_real_clk[VDEC_HEVC] <= 0) |
817 | clk = 200; |
818 | else |
819 | clk = clock_real_clk[VDEC_HEVC]; |
820 | } |
821 | |
822 | if ((clk > 500 && clk != 667)) { |
823 | if (clock_real_clk[VDEC_HEVC] == 648) |
824 | return 648; |
825 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) |
826 | clk = TL1_HEVC_MAX_CLK; |
827 | else |
828 | clk = 667; |
829 | } |
830 | |
831 | if (set_frq_enable && hevc_frq) { |
832 | pr_info("Set the hevc frq is %u MHz\n", hevc_frq); |
833 | clk = hevc_frq; |
834 | } |
835 | |
836 | vdec_set_clk(VDEC_HEVC, clk * MHz); |
837 | |
838 | clock_real_clk[VDEC_HEVC] = clk; |
839 | |
840 | pr_debug("hevc mux clock is %lu Hz\n", |
841 | clk_get_rate(gclk.hevc_mux_node->clk)); |
842 | |
843 | return clk; |
844 | } |
845 | |
846 | static int hcodec_clock_set(int clk) |
847 | { |
848 | if (clk == 1) |
849 | clk = 200; |
850 | else if (clk == 2) { |
851 | if (clock_real_clk[VDEC_HCODEC] != 648) |
852 | clk = 500; |
853 | else |
854 | clk = 648; |
855 | } else if (clk == 0) { |
856 | if (clock_real_clk[VDEC_HCODEC] == 667 || |
857 | (clock_real_clk[VDEC_HCODEC] == 648) || |
858 | clock_real_clk[VDEC_HCODEC] <= 0) |
859 | clk = 200; |
860 | else |
861 | clk = clock_real_clk[VDEC_HCODEC]; |
862 | } |
863 | |
864 | if ((clk > 500 && clk != 667)) { |
865 | if (clock_real_clk[VDEC_HCODEC] == 648) |
866 | return 648; |
867 | clk = 667; |
868 | } |
869 | |
870 | vdec_set_clk(VDEC_HCODEC, clk * MHz); |
871 | |
872 | clock_real_clk[VDEC_HCODEC] = clk; |
873 | |
874 | pr_debug("hcodec mux clock is %lu Hz\n", |
875 | clk_get_rate(gclk.hcodec_mux_node->clk)); |
876 | |
877 | return clk; |
878 | } |
879 | #endif |
880 | |
881 | static void vdec_clock_on(void) |
882 | { |
883 | mutex_lock(&gclk.vdec_mux_node->mutex); |
884 | if (!gclk.vdec_mux_node->ref_count) |
885 | clk_prepare_enable(gclk.vdec_mux_node->clk); |
886 | |
887 | gclk.vdec_mux_node->ref_count++; |
888 | mutex_unlock(&gclk.vdec_mux_node->mutex); |
889 | |
890 | pr_debug("the %-15s clock on, ref cnt: %d\n", |
891 | gclk.vdec_mux_node->name, |
892 | gclk.vdec_mux_node->ref_count); |
893 | } |
894 | |
895 | static void vdec_clock_off(void) |
896 | { |
897 | mutex_lock(&gclk.vdec_mux_node->mutex); |
898 | gclk.vdec_mux_node->ref_count--; |
899 | if (!gclk.vdec_mux_node->ref_count) |
900 | clk_disable_unprepare(gclk.vdec_mux_node->clk); |
901 | |
902 | clock_real_clk[VDEC_1] = 0; |
903 | mutex_unlock(&gclk.vdec_mux_node->mutex); |
904 | |
905 | pr_debug("the %-15s clock off, ref cnt: %d\n", |
906 | gclk.vdec_mux_node->name, |
907 | gclk.vdec_mux_node->ref_count); |
908 | } |
909 | |
910 | static void hcodec_clock_on(void) |
911 | { |
912 | mutex_lock(&gclk.hcodec_mux_node->mutex); |
913 | if (!gclk.hcodec_mux_node->ref_count) |
914 | clk_prepare_enable(gclk.hcodec_mux_node->clk); |
915 | |
916 | gclk.hcodec_mux_node->ref_count++; |
917 | mutex_unlock(&gclk.hcodec_mux_node->mutex); |
918 | |
919 | pr_debug("the %-15s clock on, ref cnt: %d\n", |
920 | gclk.hcodec_mux_node->name, |
921 | gclk.hcodec_mux_node->ref_count); |
922 | } |
923 | |
924 | static void hcodec_clock_off(void) |
925 | { |
926 | mutex_lock(&gclk.hcodec_mux_node->mutex); |
927 | gclk.hcodec_mux_node->ref_count--; |
928 | if (!gclk.hcodec_mux_node->ref_count) |
929 | clk_disable_unprepare(gclk.hcodec_mux_node->clk); |
930 | |
931 | mutex_unlock(&gclk.hcodec_mux_node->mutex); |
932 | |
933 | pr_debug("the %-15s clock off, ref cnt: %d\n", |
934 | gclk.hcodec_mux_node->name, |
935 | gclk.hcodec_mux_node->ref_count); |
936 | } |
937 | |
938 | static void hevc_clock_on(void) |
939 | { |
940 | mutex_lock(&gclk.hevc_mux_node->mutex); |
941 | if (!gclk.hevc_mux_node->ref_count) |
942 | clk_prepare_enable(gclk.hevc_mux_node->clk); |
943 | |
944 | gclk.hevc_mux_node->ref_count++; |
945 | WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); |
946 | mutex_unlock(&gclk.hevc_mux_node->mutex); |
947 | |
948 | pr_debug("the %-15s clock on, ref cnt: %d\n", |
949 | gclk.hevc_mux_node->name, |
950 | gclk.hevc_mux_node->ref_count); |
951 | } |
952 | |
953 | static void hevc_clock_off(void) |
954 | { |
955 | mutex_lock(&gclk.hevc_mux_node->mutex); |
956 | gclk.hevc_mux_node->ref_count--; |
957 | if (!gclk.hevc_mux_node->ref_count) |
958 | clk_disable_unprepare(gclk.hevc_mux_node->clk); |
959 | |
960 | clock_real_clk[VDEC_HEVC] = 0; |
961 | mutex_unlock(&gclk.hevc_mux_node->mutex); |
962 | |
963 | pr_debug("the %-15s clock off, ref cnt: %d\n", |
964 | gclk.hevc_mux_node->name, |
965 | gclk.hevc_mux_node->ref_count); |
966 | } |
967 | |
968 | static void hevc_back_clock_on(void) |
969 | { |
970 | mutex_lock(&gclk.hevc_back_mux_node->mutex); |
971 | if (!gclk.hevc_back_mux_node->ref_count) |
972 | clk_prepare_enable(gclk.hevc_back_mux_node->clk); |
973 | |
974 | gclk.hevc_back_mux_node->ref_count++; |
975 | WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); |
976 | mutex_unlock(&gclk.hevc_back_mux_node->mutex); |
977 | |
978 | pr_debug("the %-15s clock on, ref cnt: %d\n", |
979 | gclk.hevc_back_mux_node->name, |
980 | gclk.hevc_back_mux_node->ref_count); |
981 | } |
982 | |
983 | static void hevc_back_clock_off(void) |
984 | { |
985 | mutex_lock(&gclk.hevc_back_mux_node->mutex); |
986 | gclk.hevc_back_mux_node->ref_count--; |
987 | if (!gclk.hevc_back_mux_node->ref_count) |
988 | clk_disable_unprepare(gclk.hevc_back_mux_node->clk); |
989 | |
990 | clock_real_clk[VDEC_HEVC] = 0; |
991 | mutex_unlock(&gclk.hevc_back_mux_node->mutex); |
992 | |
993 | pr_debug("the %-15s clock off, ref cnt: %d\n", |
994 | gclk.hevc_back_mux_node->name, |
995 | gclk.hevc_back_mux_node->ref_count); |
996 | } |
997 | |
998 | static int vdec_clock_get(enum vdec_type_e core) |
999 | { |
1000 | if (core >= VDEC_MAX) |
1001 | return 0; |
1002 | |
1003 | return clock_real_clk[core]; |
1004 | } |
1005 | |
1006 | #define INCLUDE_FROM_ARCH_CLK_MGR |
1007 | |
1008 | /*#define VDEC_HAS_VDEC2*/ |
1009 | #define VDEC_HAS_HEVC |
1010 | #define VDEC_HAS_VDEC_HCODEC |
1011 | #define VDEC_HAS_CLK_SETTINGS |
1012 | #define CLK_FOR_CPU {\ |
1013 | AM_MESON_CPU_MAJOR_ID_GXBB,\ |
1014 | AM_MESON_CPU_MAJOR_ID_GXTVBB,\ |
1015 | AM_MESON_CPU_MAJOR_ID_GXL,\ |
1016 | AM_MESON_CPU_MAJOR_ID_GXM,\ |
1017 | AM_MESON_CPU_MAJOR_ID_TXL,\ |
1018 | AM_MESON_CPU_MAJOR_ID_TXLX,\ |
1019 | AM_MESON_CPU_MAJOR_ID_G12A,\ |
1020 | AM_MESON_CPU_MAJOR_ID_G12B,\ |
1021 | AM_MESON_CPU_MAJOR_ID_SM1,\ |
1022 | AM_MESON_CPU_MAJOR_ID_TL1,\ |
1023 | AM_MESON_CPU_MAJOR_ID_TM2,\ |
1024 | 0} |
1025 | #include "clk.h" |
1026 | |
1027 | module_param(set_frq_enable, uint, 0664); |
1028 | MODULE_PARM_DESC(set_frq_enable, "\n set frequency enable\n"); |
1029 | |
1030 | module_param(vdec_frq, uint, 0664); |
1031 | MODULE_PARM_DESC(vdec_frq, "\n set vdec frequency\n"); |
1032 | |
1033 | module_param(hevc_frq, uint, 0664); |
1034 | MODULE_PARM_DESC(hevc_frq, "\n set hevc frequency\n"); |
1035 | |
1036 | module_param(hevcb_frq, uint, 0664); |
1037 | MODULE_PARM_DESC(hevcb_frq, "\n set hevcb frequency\n"); |
1038 | |
1039 | ARCH_VDEC_CLK_INIT(); |
1040 | ARCH_VDEC_CLK_EXIT(); |
1041 | |
1042 | MODULE_LICENSE("GPL"); |
1043 |