summaryrefslogtreecommitdiff
path: root/drivers/common/media_clock/clk/clk.c (plain)
blob: 144006c158194a952bfe321d1b1e2d2f09dbe3da
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 || format == VFORMAT_AV1) {
339 ret_clk = hevc_clock_set(clk);
340 clock_source_wxhxfps_saved[VDEC_HEVC] = width * height * fps;
341 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
342 ret_clk = hevc_back_clock_set(clk);
343 clock_source_wxhxfps_saved[VDEC_HEVCB] = width * height * fps;
344 }
345 } else if (format == VFORMAT_H264_ENC || format == VFORMAT_JPEG_ENC) {
346 ret_clk = hcodec_clock_set(clk);
347 clock_source_wxhxfps_saved[VDEC_HCODEC] = width * height * fps;
348 } else if (format == VFORMAT_H264_4K2K &&
349 get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_M8) {
350 ret_clk = vdec2_clock_set(clk);
351 clock_source_wxhxfps_saved[VDEC_2] = width * height * fps;
352 ret_clk = vdec_clock_set(clk);
353 clock_source_wxhxfps_saved[VDEC_1] = width * height * fps;
354 } else {
355 ret_clk = vdec_clock_set(clk);
356 clock_source_wxhxfps_saved[VDEC_1] = width * height * fps;
357 }
358 return ret_clk;
359}
360EXPORT_SYMBOL(vdec_source_changed_for_clk_set);
361
362static int register_vdec_clk_mgr_per_cpu(int cputype,
363 enum vdec_type_e vdec_type, struct chip_vdec_clk_s *t_mgr)
364{
365
366 struct chip_vdec_clk_s *mgr;
367
368 if (cputype != get_cpu_major_id() || vdec_type >= VDEC_MAX) {
369 /*
370 *pr_info("ignore vdec clk mgr for vdec[%d] cpu=%d\n",
371 *vdec_type, cputype);
372 */
373 return 0; /* ignore don't needed firmare. */
374 }
375 mgr = kmalloc(sizeof(struct chip_vdec_clk_s), GFP_KERNEL);
376 if (!mgr)
377 return -ENOMEM;
378 *mgr = *t_mgr;
379 /*
380 *pr_info("register vdec clk mgr for vdec[%d]\n", vdec_type);
381 */
382 if (mgr->clock_init) {
383 if (mgr->clock_init()) {
384 kfree(mgr);
385 return -ENOMEM;
386 }
387 }
388 get_current_vdec_chip()->clk_mgr[vdec_type] = mgr;
389 return 0;
390}
391
392int register_vdec_clk_mgr(int cputype[], enum vdec_type_e vdec_type,
393 struct chip_vdec_clk_s *t_mgr)
394{
395 int i = 0;
396
397 while (cputype[i] > 0) {
398 register_vdec_clk_mgr_per_cpu(cputype[i], vdec_type, t_mgr);
399 i++;
400 }
401 return 0;
402}
403EXPORT_SYMBOL(register_vdec_clk_mgr);
404
405int unregister_vdec_clk_mgr(enum vdec_type_e vdec_type)
406{
407 kfree(get_current_vdec_chip()->clk_mgr[vdec_type]);
408
409 return 0;
410}
411EXPORT_SYMBOL(unregister_vdec_clk_mgr);
412
413static int register_vdec_clk_setting_per_cpu(int cputype,
414 struct clk_set_setting *setting, int size)
415{
416
417 struct clk_set_setting *p_setting;
418
419 if (cputype != get_cpu_major_id()) {
420 /*
421 *pr_info("ignore clk_set_setting for cpu=%d\n",
422 *cputype);
423 */
424 return 0; /* ignore don't needed this setting . */
425 }
426 p_setting = kmalloc(size, GFP_KERNEL);
427 if (!p_setting)
428 return -ENOMEM;
429 memcpy(p_setting, setting, size);
430
431 pr_info("register clk_set_setting cpu[%d]\n", cputype);
432
433 get_current_vdec_chip()->clk_setting_array = p_setting;
434 return 0;
435}
436
437int register_vdec_clk_setting(int cputype[],
438 struct clk_set_setting *p_seting, int size)
439{
440 int i = 0;
441
442 while (cputype[i] > 0) {
443 register_vdec_clk_setting_per_cpu(cputype[i], p_seting, size);
444 i++;
445 }
446 return 0;
447}
448EXPORT_SYMBOL(register_vdec_clk_setting);
449
450int unregister_vdec_clk_setting(void)
451{
452 kfree(get_current_vdec_chip()->clk_setting_array);
453
454 return 0;
455}
456EXPORT_SYMBOL(unregister_vdec_clk_setting);
457
458