• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/amlogic/media/common/arch/switch/amports_gate.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/compiler.h>
19 #include <linux/clk-provider.h>
20 #include <linux/err.h>
21 #include <linux/kernel.h>
22 #include <linux/spinlock.h>
23 #include <linux/clk.h>
24 #include "amports_gate.h"
25 #include <linux/amlogic/media/utils/vdec_reg.h>
26 #include "../../../stream_input/amports/amports_priv.h"
27 #include "../../../frame_provider/decoder/utils/vdec.h"
28 #include "../clk/clk.h"
29 
30 
31 #define DEBUG_REF 1
32 #define GATE_RESET_OK
33 
34 #ifdef GATE_RESET_OK
35 
36 struct gate_switch_node gates[] = {
37 	{
38 		.name = "demux",
39 	},
40 	{
41 		.name = "parser_top",
42 	},
43 	{
44 		.name = "vdec",
45 	},
46 	{
47 		.name = "clk_81",
48 	},
49 	{
50 		.name = "clk_vdec_mux",
51 	},
52 	{
53 		.name = "clk_hcodec_mux",
54 	},
55 	{
56 		.name = "clk_hevc_mux",
57 	},
58 	{
59 		.name = "clk_hevcb_mux",
60 	},
61 	{
62 		.name = "ahbarb0",
63 	},
64 	{
65 		.name = "asyncfifo",
66 	},
67 };
68 
69 /*
70  *mesonstream {
71  *	compatible = "amlogic, codec, streambuf";
72  *	dev_name = "mesonstream";
73  *	status = "okay";
74  *	clocks = <&clkc CLKID_DOS_PARSER
75  *		&clkc CLKID_DEMUX
76  *		&clkc CLKID_DOS
77  *		&clkc CLKID_VDEC_MUX
78  *		&clkc CLKID_HCODEC_MUX
79  *		&clkc CLKID_HEVCF_MUX
80  *		&clkc CLKID_HEVC_MUX>;
81  *	clock-names = "parser_top",
82  *		"demux",
83  *		"vdec",
84  *		"clk_vdec_mux",
85  *		"clk_hcodec_mux",
86  *		"clk_hevc_mux",
87  *		"clk_hevcb_mux";
88  *};
89  */
90 
amports_clock_gate_init(struct device * dev)91 int amports_clock_gate_init(struct device *dev)
92 {
93 	int i;
94 
95 	for (i = 0; i < sizeof(gates) / sizeof(struct gate_switch_node); i++) {
96 		gates[i].clk = devm_clk_get(dev, gates[i].name);
97 		if (IS_ERR_OR_NULL(gates[i].clk)) {
98 			gates[i].clk = NULL;
99 			pr_info("get gate %s control failed %px\n",
100 				gates[i].name,
101 				gates[i].clk);
102 		}
103 		gates[i].ref_count = 0;
104 		mutex_init(&gates[i].mutex);
105 	}
106 
107 	set_clock_gate(gates, ARRAY_SIZE(gates));
108 
109 	return 0;
110 }
111 EXPORT_SYMBOL(amports_clock_gate_init);
112 
amports_gate_clk(struct gate_switch_node * gate_node,int enable)113 static int amports_gate_clk(struct gate_switch_node *gate_node, int enable)
114 {
115 	mutex_lock(&gate_node->mutex);
116 	if (enable) {
117 		if (gate_node->ref_count == 0)
118 			clk_prepare_enable(gate_node->clk);
119 
120 		gate_node->ref_count++;
121 
122 		if (DEBUG_REF)
123 			pr_debug("the %-15s clock on, ref cnt: %d\n",
124 				gate_node->name, gate_node->ref_count);
125 	} else {
126 		gate_node->ref_count--;
127 		if (gate_node->ref_count == 0)
128 			clk_disable_unprepare(gate_node->clk);
129 
130 		if (DEBUG_REF)
131 			pr_debug("the %-15s clock off, ref cnt: %d\n",
132 				gate_node->name, gate_node->ref_count);
133 	}
134 	mutex_unlock(&gate_node->mutex);
135 
136 	return 0;
137 }
138 
amports_switch_gate(const char * name,int enable)139 int amports_switch_gate(const char *name, int enable)
140 {
141 	int i;
142 
143 	for (i = 0; i < sizeof(gates) / sizeof(struct gate_switch_node); i++) {
144 		if (!strcmp(name, gates[i].name)) {
145 
146 			/*pr_info("openclose:%d gate %s control\n", enable,
147 			 *	gates[i].name);
148 			 */
149 
150 			if (gates[i].clk)
151 				amports_gate_clk(&gates[i], enable);
152 		}
153 	}
154 	return 0;
155 }
156 EXPORT_SYMBOL(amports_switch_gate);
157 
158 #else
159 /*
160  *can used for debug.
161  *on chip bringup.
162  */
amports_clock_gate_init(struct device * dev)163 int amports_clock_gate_init(struct device *dev)
164 {
165 	static int gate_inited;
166 
167 	if (gate_inited)
168 		return 0;
169 /*
170  *#define HHI_GCLK_MPEG0    0x1050
171  *#define HHI_GCLK_MPEG1    0x1051
172  *#define HHI_GCLK_MPEG2    0x1052
173  *#define HHI_GCLK_OTHER    0x1054
174  *#define HHI_GCLK_AO       0x1055
175  */
176 	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG0, 1, 1, 1);/*dos*/
177 	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 25, 1);/*U_parser_top()*/
178 	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 0xff, 6, 8);/*aiu()*/
179 	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 4, 1);/*demux()*/
180 	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG1, 1, 2, 1);/*audio in()*/
181 	WRITE_HHI_REG_BITS(HHI_GCLK_MPEG2, 1, 25, 1);/*VPU Interrupt*/
182 	gate_inited++;
183 
184 
185 
186 	return 0;
187 }
188 EXPORT_SYMBOL(amports_clock_gate_init);
189 
190 
amports_switch_gate(const char * name,int enable)191 int amports_switch_gate(const char *name, int enable)
192 {
193 	return 0;
194 }
195 EXPORT_SYMBOL(amports_switch_gate);
196 
197 #endif
198