• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
44 static 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 
vdec_clock_init(void)70 int 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 }
77 EXPORT_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  */
vdec_clock_set(int clk)86 int 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 }
94 EXPORT_SYMBOL(vdec_clock_set);
95 
vdec_clock_enable(void)96 void vdec_clock_enable(void)
97 {
98 	vdec_clock_set(1);
99 }
100 EXPORT_SYMBOL(vdec_clock_enable);
101 
vdec_clock_hi_enable(void)102 void vdec_clock_hi_enable(void)
103 {
104 	vdec_clock_set(2);
105 }
106 EXPORT_SYMBOL(vdec_clock_hi_enable);
107 
vdec_clock_on(void)108 void vdec_clock_on(void)
109 {
110 	IF_HAVE_RUN(p_vdec(), clock_on);
111 }
112 EXPORT_SYMBOL(vdec_clock_on);
113 
vdec_clock_off(void)114 void vdec_clock_off(void)
115 {
116 	IF_HAVE_RUN(p_vdec(), clock_off);
117 	clock_source_wxhxfps_saved[VDEC_1] = 0;
118 }
119 EXPORT_SYMBOL(vdec_clock_off);
120 
vdec2_clock_set(int clk)121 int 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 }
129 EXPORT_SYMBOL(vdec2_clock_set);
130 
vdec2_clock_enable(void)131 void vdec2_clock_enable(void)
132 {
133 	vdec2_clock_set(1);
134 }
135 EXPORT_SYMBOL(vdec2_clock_enable);
136 
vdec2_clock_hi_enable(void)137 void vdec2_clock_hi_enable(void)
138 {
139 	vdec2_clock_set(2);
140 }
141 EXPORT_SYMBOL(vdec2_clock_hi_enable);
142 
vdec2_clock_on(void)143 void vdec2_clock_on(void)
144 {
145 	IF_HAVE_RUN(p_vdec2(), clock_on);
146 }
147 EXPORT_SYMBOL(vdec2_clock_on);
148 
vdec2_clock_off(void)149 void vdec2_clock_off(void)
150 {
151 	IF_HAVE_RUN(p_vdec2(), clock_off);
152 	clock_source_wxhxfps_saved[VDEC_2] = 0;
153 }
154 EXPORT_SYMBOL(vdec2_clock_off);
155 
hcodec_clock_set(int clk)156 int 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 }
164 EXPORT_SYMBOL(hcodec_clock_set);
165 
hcodec_clock_enable(void)166 void hcodec_clock_enable(void)
167 {
168 	hcodec_clock_set(1);
169 }
170 EXPORT_SYMBOL(hcodec_clock_enable);
171 
hcodec_clock_hi_enable(void)172 void hcodec_clock_hi_enable(void)
173 {
174 	hcodec_clock_set(2);
175 }
176 EXPORT_SYMBOL(hcodec_clock_hi_enable);
177 
hcodec_clock_on(void)178 void hcodec_clock_on(void)
179 {
180 	IF_HAVE_RUN(p_vdec_hcodec(), clock_on);
181 }
182 EXPORT_SYMBOL(hcodec_clock_on);
183 
hcodec_clock_off(void)184 void hcodec_clock_off(void)
185 {
186 	IF_HAVE_RUN(p_vdec_hcodec(), clock_off);
187 	clock_source_wxhxfps_saved[VDEC_HCODEC] = 0;
188 }
189 EXPORT_SYMBOL(hcodec_clock_off);
190 
hevc_back_clock_init(void)191 int 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 }
198 EXPORT_SYMBOL(hevc_back_clock_init);
199 
hevc_back_clock_set(int clk)200 int 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 }
208 EXPORT_SYMBOL(hevc_back_clock_set);
209 
hevc_back_clock_enable(void)210 void hevc_back_clock_enable(void)
211 {
212 	hevc_back_clock_set(1);
213 }
214 EXPORT_SYMBOL(hevc_back_clock_enable);
215 
hevc_back_clock_hi_enable(void)216 void hevc_back_clock_hi_enable(void)
217 {
218 	hevc_back_clock_set(2);
219 }
220 EXPORT_SYMBOL(hevc_back_clock_hi_enable);
221 
hevc_clock_init(void)222 int 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 }
229 EXPORT_SYMBOL(hevc_clock_init);
230 
hevc_clock_set(int clk)231 int 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 }
239 EXPORT_SYMBOL(hevc_clock_set);
240 
hevc_clock_enable(void)241 void hevc_clock_enable(void)
242 {
243 	hevc_clock_set(1);
244 }
245 EXPORT_SYMBOL(hevc_clock_enable);
246 
hevc_clock_hi_enable(void)247 void hevc_clock_hi_enable(void)
248 {
249 	hevc_clock_set(2);
250 }
251 EXPORT_SYMBOL(hevc_clock_hi_enable);
252 
hevc_back_clock_on(void)253 void hevc_back_clock_on(void)
254 {
255 	IF_HAVE_RUN(p_vdec_hevc_back(), clock_on);
256 }
257 EXPORT_SYMBOL(hevc_back_clock_on);
258 
hevc_back_clock_off(void)259 void 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 }
264 EXPORT_SYMBOL(hevc_back_clock_off);
265 
hevc_clock_on(void)266 void hevc_clock_on(void)
267 {
268 	IF_HAVE_RUN(p_vdec_hevc(), clock_on);
269 }
270 EXPORT_SYMBOL(hevc_clock_on);
271 
hevc_clock_off(void)272 void hevc_clock_off(void)
273 {
274 	IF_HAVE_RUN(p_vdec_hevc(), clock_off);
275 	clock_source_wxhxfps_saved[VDEC_HEVC] = 0;
276 }
277 EXPORT_SYMBOL(hevc_clock_off);
278 
vdec_source_get(enum vdec_type_e core)279 int vdec_source_get(enum vdec_type_e core)
280 {
281 	return clock_source_wxhxfps_saved[core];
282 }
283 EXPORT_SYMBOL(vdec_source_get);
284 
vdec_clk_get(enum vdec_type_e core)285 int vdec_clk_get(enum vdec_type_e core)
286 {
287 	return get_current_vdec_chip()->clk_mgr[core]->clock_get(core);
288 }
289 EXPORT_SYMBOL(vdec_clk_get);
290 
get_clk_with_source(int format,int w_x_h_fps)291 int 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 }
312 EXPORT_SYMBOL(get_clk_with_source);
313 
vdec_source_changed_for_clk_set(int format,int width,int height,int fps)314 int 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 }
360 EXPORT_SYMBOL(vdec_source_changed_for_clk_set);
361 
register_vdec_clk_mgr_per_cpu(int cputype,enum vdec_type_e vdec_type,struct chip_vdec_clk_s * t_mgr)362 static 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 
register_vdec_clk_mgr(int cputype[],enum vdec_type_e vdec_type,struct chip_vdec_clk_s * t_mgr)392 int 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 }
403 EXPORT_SYMBOL(register_vdec_clk_mgr);
404 
unregister_vdec_clk_mgr(enum vdec_type_e vdec_type)405 int 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 }
411 EXPORT_SYMBOL(unregister_vdec_clk_mgr);
412 
register_vdec_clk_setting_per_cpu(int cputype,struct clk_set_setting * setting,int size)413 static 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 
register_vdec_clk_setting(int cputype[],struct clk_set_setting * p_seting,int size)437 int 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 }
448 EXPORT_SYMBOL(register_vdec_clk_setting);
449 
unregister_vdec_clk_setting(void)450 int unregister_vdec_clk_setting(void)
451 {
452 	kfree(get_current_vdec_chip()->clk_setting_array);
453 
454 	return 0;
455 }
456 EXPORT_SYMBOL(unregister_vdec_clk_setting);
457 
458