blob: 52fad393f95688125fcc064c99e2652d3487365b
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 | |
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 | |
33 | #define MHz (1000000) |
34 | |
35 | struct clk_mux_s { |
36 | struct clk *vdec_clk; |
37 | struct clk *hcodec_clk; |
38 | struct clk *hevc_clk; |
39 | }; |
40 | |
41 | struct clk_mux_s gclk; |
42 | /* |
43 | *HHI_VDEC_CLK_CNTL |
44 | *0x1078[11:9] (fclk = 2000MHz) |
45 | *0: fclk_div4 |
46 | *1: fclk_div3 |
47 | *2: fclk_div5 |
48 | *3: fclk_div7 |
49 | *4: mpll_clk_out1 |
50 | *5: mpll_clk_out2 |
51 | *0x1078[6:0] |
52 | *divider |
53 | *0x1078[8] |
54 | *enable |
55 | */ |
56 | |
57 | void vdec1_set_clk(int source, int div) |
58 | { |
59 | pr_info("vdec1_set_clk %d, %d\n", source, div); |
60 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (source << 9) | (div - 1), 0, 16); |
61 | } |
62 | EXPORT_SYMBOL(vdec1_set_clk); |
63 | |
64 | void hcodec_set_clk(int source, int div) |
65 | { |
66 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, |
67 | (source << 9) | (div - 1), 16, 16); |
68 | } |
69 | EXPORT_SYMBOL(hcodec_set_clk); |
70 | |
71 | void vdec2_set_clk(int source, int div) |
72 | { |
73 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, |
74 | (source << 9) | (div - 1), 0, 16); |
75 | } |
76 | EXPORT_SYMBOL(vdec2_set_clk); |
77 | |
78 | void hevc_set_clk(int source, int div) |
79 | { |
80 | pr_info("hevc_set_clk %d, %d\n", source, div); |
81 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, |
82 | (source << 9) | (div - 1), 16, 16); |
83 | } |
84 | EXPORT_SYMBOL(hevc_set_clk); |
85 | |
86 | void clock_set_init(struct device *dev) |
87 | { |
88 | gclk.vdec_clk = devm_clk_get(dev, "clk_vdec_mux"); |
89 | if (IS_ERR(gclk.vdec_clk)) { |
90 | printk("get vdec clk err.\n"); |
91 | } |
92 | |
93 | gclk.hcodec_clk = devm_clk_get(dev, "clk_hcodec_mux"); |
94 | if (IS_ERR(gclk.hcodec_clk)) { |
95 | printk("get hcodec clk err.\n"); |
96 | } |
97 | |
98 | gclk.hevc_clk = devm_clk_get(dev, "clk_hevc_mux"); |
99 | if (IS_ERR(gclk.hevc_clk)) { |
100 | printk("get hevc clk err.\n"); |
101 | } |
102 | } |
103 | EXPORT_SYMBOL(clock_set_init); |
104 | |
105 | void vdec_get_clk_source(int clk, int *source, int *div, int *rclk) |
106 | { |
107 | #define source_div4 (0) |
108 | #define source_div3 (1) |
109 | #define source_div5 (2) |
110 | #define source_div7 (3) |
111 | if (clk > 500) { |
112 | *source = source_div3; |
113 | *div = 1; |
114 | *rclk = 667; |
115 | } else if (clk >= 500) { |
116 | *source = source_div4; |
117 | *div = 1; |
118 | *rclk = 500; |
119 | } else if (clk >= 400) { |
120 | *source = source_div5; |
121 | *div = 1; |
122 | *rclk = 400; |
123 | } else if (clk >= 333) { |
124 | *source = source_div3; |
125 | *div = 2; |
126 | *rclk = 333; |
127 | } else if (clk >= 200) { |
128 | *source = source_div5; |
129 | *div = 2; |
130 | *rclk = 200; |
131 | } else if (clk >= 166) { |
132 | *source = source_div4; |
133 | *div = 3; |
134 | *rclk = 166; |
135 | } else if (clk >= 133) { |
136 | *source = source_div5; |
137 | *div = 3; |
138 | *rclk = 133; |
139 | } else if (clk >= 100) { |
140 | *source = source_div5; |
141 | *div = 4; |
142 | *rclk = 100; |
143 | } else if (clk >= 50) { |
144 | *source = source_div5; |
145 | *div = 8; |
146 | *rclk = 50; |
147 | } else { |
148 | *source = source_div5; |
149 | *div = 20; |
150 | *rclk = 10; |
151 | } |
152 | } |
153 | EXPORT_SYMBOL(vdec_get_clk_source); |
154 | |
155 | static int vdec_set_clk(int dec, int rate) |
156 | { |
157 | struct clk *clk = NULL; |
158 | |
159 | switch (dec) { |
160 | case VDEC_1: |
161 | clk = gclk.vdec_clk; |
162 | WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); |
163 | break; |
164 | |
165 | case VDEC_HCODEC: |
166 | clk = gclk.hcodec_clk; |
167 | WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15); |
168 | break; |
169 | |
170 | case VDEC_2: |
171 | clk = gclk.vdec_clk; |
172 | WRITE_VREG(DOS_GCLK_EN1, 0x3ff); |
173 | break; |
174 | |
175 | case VDEC_HEVC: |
176 | clk = gclk.hevc_clk; |
177 | WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); |
178 | break; |
179 | |
180 | case VDEC_MAX: |
181 | break; |
182 | |
183 | default: |
184 | pr_info("invaild vdec type.\n"); |
185 | } |
186 | |
187 | clk_set_rate(clk, rate); |
188 | |
189 | return 0; |
190 | } |
191 | |
192 | static bool is_gp0_div2 = true; |
193 | |
194 | /* set gp0 648M vdec use gp0 clk*/ |
195 | #define VDEC1_648M() \ |
196 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (0), 0, 16) |
197 | |
198 | #define HEVC_648M() \ |
199 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (0), 16, 16) |
200 | |
201 | /*set gp0 1296M vdec use gp0 clk div2*/ |
202 | #define VDEC1_648M_DIV() \ |
203 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, (6 << 9) | (1), 0, 16) |
204 | |
205 | #define HEVC_648M_DIV() \ |
206 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, (6 << 9) | (1), 16, 16) |
207 | |
208 | #define VDEC1_WITH_GP_PLL() \ |
209 | ((READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0xe00) == 0xc00) |
210 | #define HEVC_WITH_GP_PLL() \ |
211 | ((READ_HHI_REG(HHI_VDEC2_CLK_CNTL) & 0xe000000) == 0xc000000) |
212 | |
213 | #define VDEC1_CLOCK_ON() \ |
214 | do { if (is_meson_m8_cpu()) { \ |
215 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \ |
216 | WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \ |
217 | } else { \ |
218 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 8, 1); \ |
219 | WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 15, 1); \ |
220 | WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 0, 8, 1); \ |
221 | WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10); \ |
222 | } \ |
223 | } while (0) |
224 | |
225 | #define VDEC2_CLOCK_ON() do {\ |
226 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 8, 1); \ |
227 | WRITE_VREG(DOS_GCLK_EN1, 0x3ff);\ |
228 | } while (0) |
229 | |
230 | #define HCODEC_CLOCK_ON() do {\ |
231 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 1, 24, 1); \ |
232 | WRITE_VREG_BITS(DOS_GCLK_EN0, 0x7fff, 12, 15);\ |
233 | } while (0) |
234 | #define HEVC_CLOCK_ON() do {\ |
235 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 1, 24, 1); \ |
236 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 31, 1); \ |
237 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 0, 24, 1); \ |
238 | WRITE_VREG(DOS_GCLK_EN3, 0xffffffff);\ |
239 | } while (0) |
240 | #define VDEC1_SAFE_CLOCK() do {\ |
241 | WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, \ |
242 | READ_HHI_REG(HHI_VDEC_CLK_CNTL) & 0x7f, 0, 7); \ |
243 | WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 8, 1); \ |
244 | WRITE_HHI_REG_BITS(HHI_VDEC3_CLK_CNTL, 1, 15, 1);\ |
245 | } while (0) |
246 | |
247 | #define VDEC1_CLOCK_OFF() \ |
248 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 8, 1) |
249 | #define VDEC2_CLOCK_OFF() \ |
250 | WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 8, 1) |
251 | #define HCODEC_CLOCK_OFF() \ |
252 | WRITE_HHI_REG_BITS(HHI_VDEC_CLK_CNTL, 0, 24, 1) |
253 | #define HEVC_SAFE_CLOCK() do { \ |
254 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \ |
255 | (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 16) & 0x7f, 16, 7);\ |
256 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, \ |
257 | (READ_HHI_REG(HHI_VDEC2_CLK_CNTL) >> 25) & 0x7f, 25, 7);\ |
258 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 24, 1); \ |
259 | WRITE_HHI_REG_BITS(HHI_VDEC4_CLK_CNTL, 1, 31, 1);\ |
260 | } while (0) |
261 | |
262 | #define HEVC_CLOCK_OFF() WRITE_HHI_REG_BITS(HHI_VDEC2_CLK_CNTL, 0, 24, 1) |
263 | |
264 | static int clock_real_clk[VDEC_MAX + 1]; |
265 | static struct gp_pll_user_handle_s *gp_pll_user_vdec, *gp_pll_user_hevc; |
266 | |
267 | static int gp_pll_user_cb_vdec(struct gp_pll_user_handle_s *user, int event) |
268 | { |
269 | pr_info("gp_pll_user_cb_vdec call\n"); |
270 | if (event == GP_PLL_USER_EVENT_GRANT) { |
271 | if (!IS_ERR(gclk.vdec_clk)) { |
272 | vdec_set_clk(VDEC_1, 648 * MHz); |
273 | pr_info("get clock : %lu\n", |
274 | clk_get_rate(gclk.vdec_clk)); |
275 | } |
276 | } |
277 | return 0; |
278 | } |
279 | |
280 | /* |
281 | *enum vformat_e { |
282 | * VFORMAT_MPEG12 = 0, |
283 | * VFORMAT_MPEG4, |
284 | * VFORMAT_H264, |
285 | * VFORMAT_MJPEG, |
286 | * VFORMAT_REAL, |
287 | * VFORMAT_JPEG, |
288 | * VFORMAT_VC1, |
289 | * VFORMAT_AVS, |
290 | * VFORMAT_YUV, |
291 | * VFORMAT_H264MVC, |
292 | * VFORMAT_H264_4K2K, |
293 | * VFORMAT_HEVC, |
294 | * VFORMAT_H264_ENC, |
295 | * VFORMAT_JPEG_ENC, |
296 | * VFORMAT_VP9, |
297 | * VFORMAT_MAX |
298 | *}; |
299 | *sample: |
300 | *{{1280*720*30, 100}, {1920*1080*30, 166}, {1920*1080*60, 333}, |
301 | * {4096*2048*30, 600}, {4096*2048*60, 600}, {INT_MAX, 600},} |
302 | *mean: |
303 | *width * height * fps |
304 | *<720p30fps clk=100MHZ |
305 | *>=720p30fps & < 1080p30fps clk=166MHZ |
306 | *>=1080p 30fps & < 1080p60fps clk=333MHZ |
307 | */ |
308 | static struct clk_set_setting clks_for_formats[] = { |
309 | { /*[VFORMAT_MPEG12] */ |
310 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, |
311 | {1920 * 1080 * 60, 333}, |
312 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
313 | 600}, {INT_MAX, 600}, |
314 | } |
315 | }, |
316 | { /*[VFORMAT_MPEG4] */ |
317 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, |
318 | {1920 * 1080 * 60, 333}, |
319 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
320 | 600}, {INT_MAX, 600}, |
321 | } |
322 | }, |
323 | { /*[VFORMAT_H264] */ |
324 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 21, 166}, |
325 | {1920 * 1080 * 30, 333}, |
326 | {1920 * 1080 * 60, 600}, {4096 * 2048 * 60, |
327 | 600}, {INT_MAX, 600}, |
328 | } |
329 | }, |
330 | { /*[VFORMAT_MJPEG] */ |
331 | {{1280 * 720 * 30, 200}, {1920 * 1080 * 30, 200}, |
332 | {1920 * 1080 * 60, 333}, |
333 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
334 | 600}, {INT_MAX, 600}, |
335 | } |
336 | }, |
337 | { /*[VFORMAT_REAL] */ |
338 | {{1280 * 720 * 20, 200}, {1920 * 1080 * 30, 500}, |
339 | {1920 * 1080 * 60, 500}, |
340 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
341 | 600}, {INT_MAX, 600}, |
342 | } |
343 | }, |
344 | { /*[VFORMAT_JPEG] */ |
345 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, |
346 | {1920 * 1080 * 60, 333}, |
347 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
348 | 600}, {INT_MAX, 600}, |
349 | } |
350 | }, |
351 | { /*[VFORMAT_VC1] */ |
352 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, |
353 | {1920 * 1080 * 60, 333}, |
354 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
355 | 600}, {INT_MAX, 600}, |
356 | } |
357 | }, |
358 | { /*[VFORMAT_AVS] */ |
359 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 166}, |
360 | {1920 * 1080 * 60, 333}, |
361 | {4096 * 2048 * 30, 600}, {4096 * 2048 * 60, |
362 | 600}, {INT_MAX, 600}, |
363 | } |
364 | }, |
365 | { /*[VFORMAT_YUV] */ |
366 | {{1280 * 720 * 30, 100}, {INT_MAX, 100}, |
367 | {0, 0}, {0, 0}, {0, 0}, {0, 0}, |
368 | } |
369 | }, |
370 | { /*VFORMAT_H264MVC */ |
371 | {{1280 * 720 * 30, 333}, {1920 * 1080 * 30, 333}, |
372 | {4096 * 2048 * 60, 600}, |
373 | {INT_MAX, 630}, {0, 0}, {0, 0}, |
374 | } |
375 | }, |
376 | { /*VFORMAT_H264_4K2K */ |
377 | {{1280 * 720 * 30, 600}, {4096 * 2048 * 60, 630}, |
378 | {INT_MAX, 630}, |
379 | {0, 0}, {0, 0}, {0, 0}, |
380 | } |
381 | }, |
382 | { /*VFORMAT_HEVC */ |
383 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 60, 600}, |
384 | {4096 * 2048 * 25, 630}, |
385 | {4096 * 2048 * 30, 630}, {4096 * 2048 * 60, |
386 | 630}, {INT_MAX, 630}, |
387 | } |
388 | }, |
389 | { /*VFORMAT_H264_ENC */ |
390 | {{1280 * 720 * 30, 0}, {INT_MAX, 0}, |
391 | {0, 0}, {0, 0}, {0, 0}, {0, 0}, |
392 | } |
393 | }, |
394 | { /*VFORMAT_JPEG_ENC */ |
395 | {{1280 * 720 * 30, 0}, {INT_MAX, 0}, |
396 | {0, 0}, {0, 0}, {0, 0}, {0, 0}, |
397 | } |
398 | }, |
399 | { /*VFORMAT_VP9 */ |
400 | {{1280 * 720 * 30, 100}, {1920 * 1080 * 30, 100}, |
401 | {1920 * 1080 * 60, 166}, |
402 | {4096 * 2048 * 30, 333}, {4096 * 2048 * 60, |
403 | 630}, {INT_MAX, 630}, |
404 | } |
405 | }, |
406 | |
407 | }; |
408 | |
409 | static int vdec_clock_init(void) |
410 | { |
411 | gp_pll_user_vdec = gp_pll_user_register("vdec", 0, gp_pll_user_cb_vdec); |
412 | if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) |
413 | is_gp0_div2 = false; |
414 | else |
415 | is_gp0_div2 = true; |
416 | |
417 | if (get_cpu_type() >= MESON_CPU_MAJOR_ID_GXL) { |
418 | pr_info("used fix clk for vdec clk source!\n"); |
419 | //update_vdec_clk_config_settings(1);//DEBUG_TMP |
420 | } |
421 | return (gp_pll_user_vdec) ? 0 : -ENOMEM; |
422 | } |
423 | #if 0 |
424 | static void update_clk_with_clk_configs(int clk, int *source, int *div, |
425 | int *rclk) |
426 | { |
427 | unsigned int config = 0;//get_vdec_clk_config_settings();//DEBUG_TMP |
428 | |
429 | if (!config) |
430 | return; |
431 | if (config >= 10) { |
432 | int wantclk; |
433 | |
434 | wantclk = config; |
435 | vdec_get_clk_source(wantclk, source, div, rclk); |
436 | } |
437 | } |
438 | #endif |
439 | #define NO_GP0_PLL 0//(get_vdec_clk_config_settings() == 1)//DEBUG_TMP |
440 | #define ALWAYS_GP0_PLL 0//(get_vdec_clk_config_settings() == 2)//DEBUG_TMP |
441 | |
442 | static int vdec_clock_set(int clk) |
443 | { |
444 | int use_gpll = 0; |
445 | int clk_seted = 0; |
446 | int pll_wait = 0; |
447 | |
448 | if (clk == 1) |
449 | clk = 200; |
450 | else if (clk == 2) { |
451 | if (clock_real_clk[VDEC_1] != 648) |
452 | clk = 500; |
453 | else |
454 | clk = 648; |
455 | } else if (clk == 0) { |
456 | /* |
457 | *used for release gp pull. |
458 | *if used, release it. |
459 | *if not used gp pll |
460 | *do nothing. |
461 | */ |
462 | if (clock_real_clk[VDEC_1] == 667 || |
463 | (clock_real_clk[VDEC_1] == 648) || |
464 | clock_real_clk[VDEC_1] <= 0) |
465 | clk = 200; |
466 | else |
467 | clk = clock_real_clk[VDEC_1]; |
468 | } |
469 | |
470 | if ((clk > 500 && clk != 667)) { |
471 | if (clock_real_clk[VDEC_1] == 648) |
472 | return 648; |
473 | |
474 | gp_pll_request(gp_pll_user_vdec); |
475 | |
476 | while (pll_wait++ < 1000000) { |
477 | if (clk_get_rate(gclk.vdec_clk) == 648) { |
478 | clk_seted = 1; |
479 | break; |
480 | } |
481 | udelay(1); |
482 | } |
483 | |
484 | if (!clk_seted) { |
485 | use_gpll = 0; |
486 | clk = 667; |
487 | pr_info("get pll failed used fix pll\n"); |
488 | } |
489 | } |
490 | |
491 | if (!clk_seted) {/*if 648 not set, */ |
492 | vdec_set_clk(VDEC_1, clk * MHz); |
493 | pr_info("get clock : %lu\n", clk_get_rate(gclk.vdec_clk)); |
494 | } |
495 | |
496 | if (!use_gpll) |
497 | gp_pll_release(gp_pll_user_vdec); |
498 | |
499 | clock_real_clk[VDEC_1] = clk; |
500 | pr_info("vdec_clock_set to %d\n", clk); |
501 | |
502 | return clk; |
503 | } |
504 | |
505 | static void vdec_clock_on(void) |
506 | { |
507 | clk_prepare_enable(gclk.vdec_clk); |
508 | } |
509 | |
510 | static void vdec_clock_off(void) |
511 | { |
512 | clk_disable_unprepare(gclk.vdec_clk); |
513 | clock_real_clk[VDEC_1] = 0; |
514 | gp_pll_release(gp_pll_user_vdec); |
515 | } |
516 | |
517 | static int hcodec_clock_set(int clk) |
518 | { |
519 | clk_set_rate(gclk.hcodec_clk, clk * MHz); |
520 | clock_real_clk[VDEC_HCODEC] = clk; |
521 | return clk; |
522 | } |
523 | |
524 | static void hcodec_clock_on(void) |
525 | { |
526 | clk_prepare_enable(gclk.hcodec_clk); |
527 | } |
528 | |
529 | static void hcodec_clock_off(void) |
530 | { |
531 | clk_disable_unprepare(gclk.hcodec_clk); |
532 | } |
533 | |
534 | static int gp_pll_user_cb_hevc(struct gp_pll_user_handle_s *user, int event) |
535 | { |
536 | pr_info("gp_pll_user_cb_hevc callback\n"); |
537 | if (event == GP_PLL_USER_EVENT_GRANT) { |
538 | if (!IS_ERR(gclk.hevc_clk)) { |
539 | vdec_set_clk(VDEC_HEVC, 648 * MHz); |
540 | pr_info("get clock : %lu\n", |
541 | clk_get_rate(gclk.hevc_clk)); |
542 | } |
543 | } |
544 | |
545 | return 0; |
546 | } |
547 | |
548 | static int hevc_clock_init(void) |
549 | { |
550 | gp_pll_user_hevc = gp_pll_user_register("hevc", 0, gp_pll_user_cb_hevc); |
551 | |
552 | return (gp_pll_user_hevc) ? 0 : -ENOMEM; |
553 | } |
554 | |
555 | static int hevc_clock_set(int clk) |
556 | { |
557 | int use_gpll = 0; |
558 | int clk_seted = 0; |
559 | int pll_wait = 0; |
560 | |
561 | if (clk == 1) |
562 | clk = 200; |
563 | else if (clk == 2) { |
564 | if (clock_real_clk[VDEC_HEVC] != 648) |
565 | clk = 500; |
566 | else |
567 | clk = 648; |
568 | } else if (clk == 0) { |
569 | if (clock_real_clk[VDEC_HEVC] == 667 || |
570 | (clock_real_clk[VDEC_HEVC] == 648) || |
571 | clock_real_clk[VDEC_HEVC] <= 0) |
572 | clk = 200; |
573 | else |
574 | clk = clock_real_clk[VDEC_HEVC]; |
575 | } |
576 | |
577 | if ((clk > 500 && clk != 667)) { |
578 | if (clock_real_clk[VDEC_HEVC] == 648) |
579 | return 648; |
580 | |
581 | gp_pll_request(gp_pll_user_hevc); |
582 | |
583 | while (pll_wait++ < 1000000) { |
584 | if (clk_get_rate(gclk.hevc_clk) == 648) { |
585 | clk_seted = 1; |
586 | break; |
587 | } |
588 | udelay(1); |
589 | } |
590 | |
591 | if (!clk_seted) { |
592 | use_gpll = 0; |
593 | clk = 667; |
594 | pr_info("get pll failed used fix pll\n"); |
595 | } |
596 | } |
597 | |
598 | if (!clk_seted) {/*if 648 not set, */ |
599 | vdec_set_clk(VDEC_HEVC, clk * MHz); |
600 | pr_info("get clock : %lu\n", clk_get_rate(gclk.hevc_clk)); |
601 | } |
602 | |
603 | if (!use_gpll) |
604 | gp_pll_release(gp_pll_user_hevc); |
605 | |
606 | clock_real_clk[VDEC_HEVC] = clk; |
607 | pr_info("hevc_clock_set to %d\n", clk); |
608 | |
609 | return clk; |
610 | } |
611 | |
612 | static void hevc_clock_on(void) |
613 | { |
614 | clk_prepare_enable(gclk.hevc_clk); |
615 | WRITE_VREG(DOS_GCLK_EN3, 0xffffffff); |
616 | } |
617 | |
618 | static void hevc_clock_off(void) |
619 | { |
620 | clk_disable_unprepare(gclk.hevc_clk); |
621 | gp_pll_release(gp_pll_user_hevc); |
622 | clock_real_clk[VDEC_HEVC] = 0; |
623 | } |
624 | |
625 | static int vdec_clock_get(enum vdec_type_e core) |
626 | { |
627 | if (core >= VDEC_MAX) |
628 | return 0; |
629 | |
630 | return clock_real_clk[core]; |
631 | } |
632 | |
633 | #define INCLUDE_FROM_ARCH_CLK_MGR |
634 | |
635 | /*#define VDEC_HAS_VDEC2*/ |
636 | #define VDEC_HAS_HEVC |
637 | #define VDEC_HAS_VDEC_HCODEC |
638 | #define VDEC_HAS_CLK_SETTINGS |
639 | #define CLK_FOR_CPU {\ |
640 | MESON_CPU_MAJOR_ID_GXBB,\ |
641 | MESON_CPU_MAJOR_ID_GXTVBB,\ |
642 | MESON_CPU_MAJOR_ID_GXL,\ |
643 | MESON_CPU_MAJOR_ID_GXM,\ |
644 | MESON_CPU_MAJOR_ID_TXL,\ |
645 | 0} |
646 | #include "clk.h" |
647 | ARCH_VDEC_CLK_INIT(); |
648 | ARCH_VDEC_CLK_EXIT(); |
649 | |
650 | MODULE_LICENSE("GPL"); |
651 |