summaryrefslogtreecommitdiff
path: root/drivers/common/media_clock/clk/clk.c (plain)
blob: b60a08d0805beced229f1115a170bbebfb59d701
1/*
2 * drivers/amlogic/media/common/arch/clk/clk.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/kernel.h>
19#include <linux/module.h>
20#include <linux/types.h>
21#include <linux/fs.h>
22#include <linux/init.h>
23#include <linux/device.h>
24#include <linux/vmalloc.h>
25#include <linux/mm.h>
26#include <linux/vmalloc.h>
27#include <linux/slab.h>
28
29#include <linux/amlogic/media/utils/vformat.h>
30#include <linux/amlogic/cpu_version.h>
31#include "../../../stream_input/amports/amports_priv.h"
32#include "../../../frame_provider/decoder/utils/vdec.h"
33#include "../../chips/chips.h"
34#include "clk_priv.h"
35#include <linux/amlogic/media/utils/log.h>
36#include "../../chips/decoder_cpu_ver_info.h"
37
38#define p_vdec() (get_current_vdec_chip()->clk_mgr[VDEC_1])
39#define p_vdec2() (get_current_vdec_chip()->clk_mgr[VDEC_2])
40#define p_vdec_hcodec() (get_current_vdec_chip()->clk_mgr[VDEC_HCODEC])
41#define p_vdec_hevc() (get_current_vdec_chip()->clk_mgr[VDEC_HEVC])
42#define p_vdec_hevc_back() (get_current_vdec_chip()->clk_mgr[VDEC_HEVCB])
43
44static int clock_source_wxhxfps_saved[VDEC_MAX + 1];
45
46#define IF_HAVE_RUN(p, fn)\
47 do {\
48 if (p && p->fn)\
49 p->fn();\
50 } while (0)
51/*
52 *#define IF_HAVE_RUN_P1_RET(p, fn, p1)\
53 * do {\
54 * pr_debug("%s-----%d\n", __func__, clk);\
55 * if (p && p->fn)\
56 * return p->fn(p1);\
57 * else\
58 * return -1;\
59 * } while (0)
60 *
61 *#define IF_HAVE_RUN_RET(p, fn)\
62 * do {\
63 * if (p && p->fn)\
64 * return p->fn();\
65 * else\
66 * return 0;\
67 * } while (0)
68 */
69
70int vdec_clock_init(void)
71{
72 if (p_vdec() && p_vdec()->clock_init)
73 return p_vdec()->clock_init();
74 else
75 return 0;
76}
77EXPORT_SYMBOL(vdec_clock_init);
78
79/*
80 *clk ==0 :
81 * to be release.
82 * released shared clk,
83 *clk ==1 :default low clk
84 *clk ==2 :default high clk
85 */
86int vdec_clock_set(int clk)
87{
88 pr_debug("%s-----%d\n", __func__, clk);
89 if (p_vdec() && p_vdec()->clock_set)
90 return p_vdec()->clock_set(clk);
91 else
92 return -1;
93}
94EXPORT_SYMBOL(vdec_clock_set);
95
96void vdec_clock_enable(void)
97{
98 vdec_clock_set(1);
99}
100EXPORT_SYMBOL(vdec_clock_enable);
101
102void vdec_clock_hi_enable(void)
103{
104 vdec_clock_set(2);
105}
106EXPORT_SYMBOL(vdec_clock_hi_enable);
107
108void vdec_clock_on(void)
109{
110 IF_HAVE_RUN(p_vdec(), clock_on);
111}
112EXPORT_SYMBOL(vdec_clock_on);
113
114void vdec_clock_off(void)
115{
116 IF_HAVE_RUN(p_vdec(), clock_off);
117 clock_source_wxhxfps_saved[VDEC_1] = 0;
118}
119EXPORT_SYMBOL(vdec_clock_off);
120
121int vdec2_clock_set(int clk)
122{
123 pr_debug("%s-----%d\n", __func__, clk);
124 if (p_vdec2() && p_vdec2()->clock_set)
125 return p_vdec2()->clock_set(clk);
126 else
127 return -1;
128}
129EXPORT_SYMBOL(vdec2_clock_set);
130
131void vdec2_clock_enable(void)
132{
133 vdec2_clock_set(1);
134}
135EXPORT_SYMBOL(vdec2_clock_enable);
136
137void vdec2_clock_hi_enable(void)
138{
139 vdec2_clock_set(2);
140}
141EXPORT_SYMBOL(vdec2_clock_hi_enable);
142
143void vdec2_clock_on(void)
144{
145 IF_HAVE_RUN(p_vdec2(), clock_on);
146}
147EXPORT_SYMBOL(vdec2_clock_on);
148
149void vdec2_clock_off(void)
150{
151 IF_HAVE_RUN(p_vdec2(), clock_off);
152 clock_source_wxhxfps_saved[VDEC_2] = 0;
153}
154EXPORT_SYMBOL(vdec2_clock_off);
155
156int hcodec_clock_set(int clk)
157{
158 pr_debug("%s-----%d\n", __func__, clk);
159 if (p_vdec_hcodec() && p_vdec_hcodec()->clock_set)
160 return p_vdec_hcodec()->clock_set(clk);
161 else
162 return -1;
163}
164EXPORT_SYMBOL(hcodec_clock_set);
165
166void hcodec_clock_enable(void)
167{
168 hcodec_clock_set(1);
169}
170EXPORT_SYMBOL(hcodec_clock_enable);
171
172void hcodec_clock_hi_enable(void)
173{
174 hcodec_clock_set(2);
175}
176EXPORT_SYMBOL(hcodec_clock_hi_enable);
177
178void hcodec_clock_on(void)
179{
180 IF_HAVE_RUN(p_vdec_hcodec(), clock_on);
181}
182EXPORT_SYMBOL(hcodec_clock_on);
183
184void hcodec_clock_off(void)
185{
186 IF_HAVE_RUN(p_vdec_hcodec(), clock_off);
187 clock_source_wxhxfps_saved[VDEC_HCODEC] = 0;
188}
189EXPORT_SYMBOL(hcodec_clock_off);
190
191int hevc_back_clock_init(void)
192{
193 if (p_vdec_hevc_back() && p_vdec_hevc_back()->clock_init)
194 return p_vdec_hevc_back()->clock_init();
195 else
196 return 0;
197}
198EXPORT_SYMBOL(hevc_back_clock_init);
199
200int hevc_back_clock_set(int clk)
201{
202 pr_debug("%s-----%d\n", __func__, clk);
203 if (p_vdec_hevc_back() && p_vdec_hevc_back()->clock_set)
204 return p_vdec_hevc_back()->clock_set(clk);
205 else
206 return -1;
207}
208EXPORT_SYMBOL(hevc_back_clock_set);
209
210void hevc_back_clock_enable(void)
211{
212 hevc_back_clock_set(1);
213}
214EXPORT_SYMBOL(hevc_back_clock_enable);
215
216void hevc_back_clock_hi_enable(void)
217{
218 hevc_back_clock_set(2);
219}
220EXPORT_SYMBOL(hevc_back_clock_hi_enable);
221
222int hevc_clock_init(void)
223{
224 if (p_vdec_hevc() && p_vdec_hevc()->clock_init)
225 return p_vdec_hevc()->clock_init();
226 else
227 return 0;
228}
229EXPORT_SYMBOL(hevc_clock_init);
230
231int hevc_clock_set(int clk)
232{
233 pr_debug("%s-----%d\n", __func__, clk);
234 if (p_vdec_hevc() && p_vdec_hevc()->clock_set)
235 return p_vdec_hevc()->clock_set(clk);
236 else
237 return -1;
238}
239EXPORT_SYMBOL(hevc_clock_set);
240
241void hevc_clock_enable(void)
242{
243 hevc_clock_set(1);
244}
245EXPORT_SYMBOL(hevc_clock_enable);
246
247void hevc_clock_hi_enable(void)
248{
249 hevc_clock_set(2);
250}
251EXPORT_SYMBOL(hevc_clock_hi_enable);
252
253void hevc_back_clock_on(void)
254{
255 IF_HAVE_RUN(p_vdec_hevc_back(), clock_on);
256}
257EXPORT_SYMBOL(hevc_back_clock_on);
258
259void hevc_back_clock_off(void)
260{
261 IF_HAVE_RUN(p_vdec_hevc_back(), clock_off);
262 clock_source_wxhxfps_saved[VDEC_HEVCB] = 0;
263}
264EXPORT_SYMBOL(hevc_back_clock_off);
265
266void hevc_clock_on(void)
267{
268 IF_HAVE_RUN(p_vdec_hevc(), clock_on);
269}
270EXPORT_SYMBOL(hevc_clock_on);
271
272void hevc_clock_off(void)
273{
274 IF_HAVE_RUN(p_vdec_hevc(), clock_off);
275 clock_source_wxhxfps_saved[VDEC_HEVC] = 0;
276}
277EXPORT_SYMBOL(hevc_clock_off);
278
279int vdec_source_get(enum vdec_type_e core)
280{
281 return clock_source_wxhxfps_saved[core];
282}
283EXPORT_SYMBOL(vdec_source_get);
284
285int vdec_clk_get(enum vdec_type_e core)
286{
287 return get_current_vdec_chip()->clk_mgr[core]->clock_get(core);
288}
289EXPORT_SYMBOL(vdec_clk_get);
290
291int get_clk_with_source(int format, int w_x_h_fps)
292{
293 struct clk_set_setting *p_setting;
294 int i;
295 int clk = -2;
296
297 p_setting = get_current_vdec_chip()->clk_setting_array;
298 if (!p_setting || format < 0 || format > VFORMAT_MAX) {
299 pr_info("error on get_clk_with_source ,%p,%d\n",
300 p_setting, format);
301 return -1; /*no setting found. */
302 }
303 p_setting = &p_setting[format];
304 for (i = 0; i < MAX_CLK_SET; i++) {
305 if (p_setting->set[i].wh_X_fps > w_x_h_fps) {
306 clk = p_setting->set[i].clk_Mhz;
307 break;
308 }
309 }
310 return clk;
311}
312EXPORT_SYMBOL(get_clk_with_source);
313
314int vdec_source_changed_for_clk_set(int format, int width, int height, int fps)
315{
316 int clk = get_clk_with_source(format, width * height * fps);
317 int ret_clk;
318
319 if (clk < 0) {
320 pr_info("can't get valid clk for source ,%d,%d,%d\n",
321 width, height, fps);
322 if (format >= 1920 && width >= 1080 && fps >= 30)
323 clk = 2; /*default high clk */
324 else
325 clk = 0; /*default clk. */
326 }
327 if (width * height * fps == 0)
328 clk = 0;
329 /*
330 *clk == 0
331 *is used for set default clk;
332 *if used supper clk.
333 *changed to default min clk.
334 */
335
336 if (format == VFORMAT_HEVC || format == VFORMAT_VP9
337 || format == VFORMAT_AVS2) {
338 ret_clk = hevc_clock_set(clk);
339 clock_source_wxhxfps_saved[VDEC_HEVC] = width * height * fps;
340 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
341 ret_clk = hevc_back_clock_set(clk);
342 clock_source_wxhxfps_saved[VDEC_HEVCB] = width * height * fps;
343 }
344 } else if (format == VFORMAT_H264_ENC || format == VFORMAT_JPEG_ENC) {
345 ret_clk = hcodec_clock_set(clk);
346 clock_source_wxhxfps_saved[VDEC_HCODEC] = width * height * fps;
347 } else if (format == VFORMAT_H264_4K2K &&
348 get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_M8) {
349 ret_clk = vdec2_clock_set(clk);
350 clock_source_wxhxfps_saved[VDEC_2] = width * height * fps;
351 ret_clk = vdec_clock_set(clk);
352 clock_source_wxhxfps_saved[VDEC_1] = width * height * fps;
353 } else {
354 ret_clk = vdec_clock_set(clk);
355 clock_source_wxhxfps_saved[VDEC_1] = width * height * fps;
356 }
357 return ret_clk;
358}
359EXPORT_SYMBOL(vdec_source_changed_for_clk_set);
360
361static int register_vdec_clk_mgr_per_cpu(int cputype,
362 enum vdec_type_e vdec_type, struct chip_vdec_clk_s *t_mgr)
363{
364
365 struct chip_vdec_clk_s *mgr;
366
367 if (cputype != get_cpu_major_id() || vdec_type >= VDEC_MAX) {
368 /*
369 *pr_info("ignore vdec clk mgr for vdec[%d] cpu=%d\n",
370 *vdec_type, cputype);
371 */
372 return 0; /* ignore don't needed firmare. */
373 }
374 mgr = kmalloc(sizeof(struct chip_vdec_clk_s), GFP_KERNEL);
375 if (!mgr)
376 return -ENOMEM;
377 *mgr = *t_mgr;
378 /*
379 *pr_info("register vdec clk mgr for vdec[%d]\n", vdec_type);
380 */
381 if (mgr->clock_init) {
382 if (mgr->clock_init()) {
383 kfree(mgr);
384 return -ENOMEM;
385 }
386 }
387 get_current_vdec_chip()->clk_mgr[vdec_type] = mgr;
388 return 0;
389}
390
391int register_vdec_clk_mgr(int cputype[], enum vdec_type_e vdec_type,
392 struct chip_vdec_clk_s *t_mgr)
393{
394 int i = 0;
395
396 while (cputype[i] > 0) {
397 register_vdec_clk_mgr_per_cpu(cputype[i], vdec_type, t_mgr);
398 i++;
399 }
400 return 0;
401}
402EXPORT_SYMBOL(register_vdec_clk_mgr);
403
404int unregister_vdec_clk_mgr(enum vdec_type_e vdec_type)
405{
406 kfree(get_current_vdec_chip()->clk_mgr[vdec_type]);
407
408 return 0;
409}
410EXPORT_SYMBOL(unregister_vdec_clk_mgr);
411
412static int register_vdec_clk_setting_per_cpu(int cputype,
413 struct clk_set_setting *setting, int size)
414{
415
416 struct clk_set_setting *p_setting;
417
418 if (cputype != get_cpu_major_id()) {
419 /*
420 *pr_info("ignore clk_set_setting for cpu=%d\n",
421 *cputype);
422 */
423 return 0; /* ignore don't needed this setting . */
424 }
425 p_setting = kmalloc(size, GFP_KERNEL);
426 if (!p_setting)
427 return -ENOMEM;
428 memcpy(p_setting, setting, size);
429
430 pr_info("register clk_set_setting cpu[%d]\n", cputype);
431
432 get_current_vdec_chip()->clk_setting_array = p_setting;
433 return 0;
434}
435
436int register_vdec_clk_setting(int cputype[],
437 struct clk_set_setting *p_seting, int size)
438{
439 int i = 0;
440
441 while (cputype[i] > 0) {
442 register_vdec_clk_setting_per_cpu(cputype[i], p_seting, size);
443 i++;
444 }
445 return 0;
446}
447EXPORT_SYMBOL(register_vdec_clk_setting);
448
449int unregister_vdec_clk_setting(void)
450{
451 kfree(get_current_vdec_chip()->clk_setting_array);
452
453 return 0;
454}
455EXPORT_SYMBOL(unregister_vdec_clk_setting);
456
457