xref: /OK3568_Linux_fs/kernel/drivers/media/i2c/rk628/rk628_hdmirx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2020 Rockchip Electronics Co. Ltd.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Author: Shunqing Chen <csq@rock-chips.com>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/delay.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/soc/rockchip/rk_vendor_storage.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include "rk628.h"
15*4882a593Smuzhiyun #include "rk628_combrxphy.h"
16*4882a593Smuzhiyun #include "rk628_cru.h"
17*4882a593Smuzhiyun #include "rk628_hdmirx.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define INIT_FIFO_STATE			64
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define is_validfs(x) (x == 32000 || \
22*4882a593Smuzhiyun 			x == 44100 || \
23*4882a593Smuzhiyun 			x == 48000 || \
24*4882a593Smuzhiyun 			x == 88200 || \
25*4882a593Smuzhiyun 			x == 96000 || \
26*4882a593Smuzhiyun 			x == 176400 || \
27*4882a593Smuzhiyun 			x == 192000 || \
28*4882a593Smuzhiyun 			x == 768000)
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun struct rk628_audiostate {
31*4882a593Smuzhiyun 	u32 hdmirx_aud_clkrate;
32*4882a593Smuzhiyun 	u32 fs_audio;
33*4882a593Smuzhiyun 	u32 ctsn_flag;
34*4882a593Smuzhiyun 	u32 fifo_flag;
35*4882a593Smuzhiyun 	int init_state;
36*4882a593Smuzhiyun 	int pre_state;
37*4882a593Smuzhiyun 	bool fifo_int;
38*4882a593Smuzhiyun 	bool audio_enable;
39*4882a593Smuzhiyun };
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun struct rk628_audioinfo {
42*4882a593Smuzhiyun 	struct delayed_work delayed_work_audio_rate_change;
43*4882a593Smuzhiyun 	struct delayed_work delayed_work_audio;
44*4882a593Smuzhiyun 	struct mutex *confctl_mutex;
45*4882a593Smuzhiyun 	struct rk628 *rk628;
46*4882a593Smuzhiyun 	struct rk628_audiostate audio_state;
47*4882a593Smuzhiyun 	bool i2s_enabled_default;
48*4882a593Smuzhiyun 	bool i2s_enabled;
49*4882a593Smuzhiyun 	int debug;
50*4882a593Smuzhiyun 	bool fifo_ints_en;
51*4882a593Smuzhiyun 	bool ctsn_ints_en;
52*4882a593Smuzhiyun 	bool audio_present;
53*4882a593Smuzhiyun 	struct device *dev;
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
hdcp_load_keys_cb(struct rk628 * rk628,struct rk628_hdcp * hdcp)56*4882a593Smuzhiyun static int hdcp_load_keys_cb(struct rk628 *rk628, struct rk628_hdcp *hdcp)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	int size;
59*4882a593Smuzhiyun 	u8 hdcp_vendor_data[320];
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	hdcp->keys = kmalloc(HDCP_KEY_SIZE, GFP_KERNEL);
62*4882a593Smuzhiyun 	if (!hdcp->keys)
63*4882a593Smuzhiyun 		return -ENOMEM;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	hdcp->seeds = kmalloc(HDCP_KEY_SEED_SIZE, GFP_KERNEL);
66*4882a593Smuzhiyun 	if (!hdcp->seeds) {
67*4882a593Smuzhiyun 		kfree(hdcp->keys);
68*4882a593Smuzhiyun 		hdcp->keys = NULL;
69*4882a593Smuzhiyun 		return -ENOMEM;
70*4882a593Smuzhiyun 	}
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	size = rk_vendor_read(HDMIRX_HDCP1X_ID, hdcp_vendor_data, 314);
73*4882a593Smuzhiyun 	if (size < (HDCP_KEY_SIZE + HDCP_KEY_SEED_SIZE)) {
74*4882a593Smuzhiyun 		dev_dbg(rk628->dev, "HDCP: read size %d\n", size);
75*4882a593Smuzhiyun 		kfree(hdcp->keys);
76*4882a593Smuzhiyun 		hdcp->keys = NULL;
77*4882a593Smuzhiyun 		kfree(hdcp->seeds);
78*4882a593Smuzhiyun 		hdcp->seeds = NULL;
79*4882a593Smuzhiyun 		return -EINVAL;
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun 	memcpy(hdcp->keys, hdcp_vendor_data, HDCP_KEY_SIZE);
82*4882a593Smuzhiyun 	memcpy(hdcp->seeds, hdcp_vendor_data + HDCP_KEY_SIZE,
83*4882a593Smuzhiyun 	       HDCP_KEY_SEED_SIZE);
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	return 0;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
rk628_hdmi_hdcp_load_key(struct rk628 * rk628,struct rk628_hdcp * hdcp)88*4882a593Smuzhiyun static int rk628_hdmi_hdcp_load_key(struct rk628 *rk628, struct rk628_hdcp *hdcp)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	int i;
91*4882a593Smuzhiyun 	int ret;
92*4882a593Smuzhiyun 	struct hdcp_keys *hdcp_keys;
93*4882a593Smuzhiyun 	u32 seeds = 0;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	if (!hdcp->keys) {
96*4882a593Smuzhiyun 		ret = hdcp_load_keys_cb(rk628, hdcp);
97*4882a593Smuzhiyun 		if (ret) {
98*4882a593Smuzhiyun 			dev_err(rk628->dev, "HDCP: load key failed\n");
99*4882a593Smuzhiyun 			return ret;
100*4882a593Smuzhiyun 		}
101*4882a593Smuzhiyun 	}
102*4882a593Smuzhiyun 	hdcp_keys = hdcp->keys;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, HDMI_RX_HDCP_CTRL,
105*4882a593Smuzhiyun 			HDCP_ENABLE_MASK |
106*4882a593Smuzhiyun 			HDCP_ENC_EN_MASK,
107*4882a593Smuzhiyun 			HDCP_ENABLE(0) |
108*4882a593Smuzhiyun 			HDCP_ENC_EN(0));
109*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0,
110*4882a593Smuzhiyun 			SW_ADAPTER_I2CSLADR_MASK |
111*4882a593Smuzhiyun 			SW_EFUSE_HDCP_EN_MASK,
112*4882a593Smuzhiyun 			SW_ADAPTER_I2CSLADR(0) |
113*4882a593Smuzhiyun 			SW_EFUSE_HDCP_EN(1));
114*4882a593Smuzhiyun 	/* The useful data in ksv should be 5 byte */
115*4882a593Smuzhiyun 	for (i = 0; i < KSV_LEN; i++)
116*4882a593Smuzhiyun 		rk628_i2c_write(rk628, HDCP_KEY_KSV0 + i * 4,
117*4882a593Smuzhiyun 					hdcp_keys->KSV[i]);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	for (i = 0; i < HDCP_PRIVATE_KEY_SIZE; i++)
120*4882a593Smuzhiyun 		rk628_i2c_write(rk628, HDCP_KEY_DPK0 + i * 4,
121*4882a593Smuzhiyun 				hdcp_keys->devicekey[i]);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0,
124*4882a593Smuzhiyun 			SW_ADAPTER_I2CSLADR_MASK |
125*4882a593Smuzhiyun 			SW_EFUSE_HDCP_EN_MASK,
126*4882a593Smuzhiyun 			SW_ADAPTER_I2CSLADR(0) |
127*4882a593Smuzhiyun 			SW_EFUSE_HDCP_EN(0));
128*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, HDMI_RX_HDCP_CTRL,
129*4882a593Smuzhiyun 			HDCP_ENABLE_MASK |
130*4882a593Smuzhiyun 			HDCP_ENC_EN_MASK,
131*4882a593Smuzhiyun 			HDCP_ENABLE(1) |
132*4882a593Smuzhiyun 			HDCP_ENC_EN(1));
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	/* Enable decryption logic */
135*4882a593Smuzhiyun 	if (hdcp->seeds) {
136*4882a593Smuzhiyun 		seeds = (hdcp->seeds[0] & 0xff) << 8;
137*4882a593Smuzhiyun 		seeds |= (hdcp->seeds[1] & 0xff);
138*4882a593Smuzhiyun 	}
139*4882a593Smuzhiyun 	if (seeds) {
140*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, HDMI_RX_HDCP_CTRL,
141*4882a593Smuzhiyun 				   KEY_DECRIPT_ENABLE_MASK,
142*4882a593Smuzhiyun 				   KEY_DECRIPT_ENABLE(1));
143*4882a593Smuzhiyun 		rk628_i2c_write(rk628, HDMI_RX_HDCP_SEED, seeds);
144*4882a593Smuzhiyun 	} else {
145*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, HDMI_RX_HDCP_CTRL,
146*4882a593Smuzhiyun 				   KEY_DECRIPT_ENABLE_MASK,
147*4882a593Smuzhiyun 				   KEY_DECRIPT_ENABLE(0));
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	return 0;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun 
rk628_hdmirx_set_hdcp(struct rk628 * rk628,struct rk628_hdcp * hdcp,bool en)153*4882a593Smuzhiyun void rk628_hdmirx_set_hdcp(struct rk628 *rk628, struct rk628_hdcp *hdcp, bool en)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	dev_dbg(rk628->dev, "%s: %sable\n", __func__, en ? "en" : "dis");
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	if (en) {
158*4882a593Smuzhiyun 		rk628_hdmi_hdcp_load_key(rk628, hdcp);
159*4882a593Smuzhiyun 	} else {
160*4882a593Smuzhiyun 		rk628_i2c_update_bits(rk628, HDMI_RX_HDCP_CTRL,
161*4882a593Smuzhiyun 				      HDCP_ENABLE_MASK |
162*4882a593Smuzhiyun 				      HDCP_ENC_EN_MASK,
163*4882a593Smuzhiyun 				      HDCP_ENABLE(0) |
164*4882a593Smuzhiyun 				      HDCP_ENC_EN(0));
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_hdmirx_set_hdcp);
168*4882a593Smuzhiyun 
rk628_hdmirx_controller_setup(struct rk628 * rk628)169*4882a593Smuzhiyun void rk628_hdmirx_controller_setup(struct rk628 *rk628)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_HDMI20_CONTROL, 0x10000f10);
172*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_HDMI_MODE_RECOVER, 0x00000021);
173*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_PDEC_CTRL, 0xbfff8011);
174*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_PDEC_ASP_CTRL, 0x00000040);
175*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_HDMI_RESMPL_CTRL, 0x00000001);
176*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_HDMI_SYNC_CTRL, 0x00000014);
177*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_PDEC_ERR_FILTER, 0x00000008);
178*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_SCDC_I2CCONFIG, 0x01000000);
179*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_SCDC_CONFIG, 0x00000001);
180*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_SCDC_WRDATA0, 0xabcdef01);
181*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_CHLOCK_CONFIG, 0x0030c15c);
182*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_HDMI_ERROR_PROTECT, 0x000d0c98);
183*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_MD_HCTRL1, 0x00000010);
184*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_MD_HCTRL2, 0x00001738);
185*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_MD_VCTRL, 0x00000002);
186*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_MD_VTH, 0x0000073a);
187*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_MD_IL_POL, 0x00000004);
188*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_PDEC_ACRM_CTRL, 0x00000000);
189*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_HDMI_DCM_CTRL, 0x00040414);
190*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_HDMI_CKM_EVLTM, 0x00103e70);
191*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_HDMI_CKM_F, 0x0c1c0b54);
192*4882a593Smuzhiyun 	rk628_i2c_write(rk628, HDMI_RX_HDMI_RESMPL_CTRL, 0x00000001);
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	rk628_i2c_update_bits(rk628, HDMI_RX_HDCP_SETTINGS,
195*4882a593Smuzhiyun 			      HDMI_RESERVED_MASK |
196*4882a593Smuzhiyun 			      FAST_I2C_MASK |
197*4882a593Smuzhiyun 			      ONE_DOT_ONE_MASK |
198*4882a593Smuzhiyun 			      FAST_REAUTH_MASK,
199*4882a593Smuzhiyun 			      HDMI_RESERVED(1) |
200*4882a593Smuzhiyun 			      FAST_I2C(0) |
201*4882a593Smuzhiyun 			      ONE_DOT_ONE(0) |
202*4882a593Smuzhiyun 			      FAST_REAUTH(0));
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_hdmirx_controller_setup);
205*4882a593Smuzhiyun 
rk628_hdmirx_audio_fifo_init(struct rk628_audioinfo * aif)206*4882a593Smuzhiyun static void rk628_hdmirx_audio_fifo_init(struct rk628_audioinfo *aif)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s initial fifo\n", __func__);
210*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_ICLR, 0x1f);
211*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_CTRL, 0x10001);
212*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_CTRL, 0x10000);
213*4882a593Smuzhiyun 	aif->audio_state.pre_state = aif->audio_state.init_state = INIT_FIFO_STATE*4;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
rk628_hdmirx_audio_fifo_initd(struct rk628_audioinfo * aif)216*4882a593Smuzhiyun static void rk628_hdmirx_audio_fifo_initd(struct rk628_audioinfo *aif)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s double initial fifo\n", __func__);
220*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_ICLR, 0x1f);
221*4882a593Smuzhiyun 	rk628_i2c_update_bits(aif->rk628, HDMI_RX_AUD_FIFO_TH,
222*4882a593Smuzhiyun 			   AFIF_TH_START_MASK,
223*4882a593Smuzhiyun 			   AFIF_TH_START(192));
224*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_CTRL, 0x10001);
225*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_CTRL, 0x10000);
226*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_CTRL, 0x10001);
227*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_CTRL, 0x10000);
228*4882a593Smuzhiyun 	rk628_i2c_update_bits(aif->rk628, HDMI_RX_AUD_FIFO_TH,
229*4882a593Smuzhiyun 			   AFIF_TH_START_MASK,
230*4882a593Smuzhiyun 			   AFIF_TH_START(INIT_FIFO_STATE));
231*4882a593Smuzhiyun 	aif->audio_state.pre_state = aif->audio_state.init_state = INIT_FIFO_STATE*4;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
_rk628_hdmirx_audio_fs(struct rk628_audioinfo * aif)234*4882a593Smuzhiyun static u32 _rk628_hdmirx_audio_fs(struct rk628_audioinfo *aif)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun 	u64 tmdsclk = 0;
237*4882a593Smuzhiyun 	u32 clkrate = 0, cts_decoded = 0, n_decoded = 0, fs_audio = 0;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	/* fout=128*fs=ftmds*N/CTS */
240*4882a593Smuzhiyun 	rk628_i2c_read(aif->rk628, HDMI_RX_HDMI_CKM_RESULT, &clkrate);
241*4882a593Smuzhiyun 	clkrate = clkrate & 0xffff;
242*4882a593Smuzhiyun 	/* tmdsclk = (clkrate/1000) * 49500000 */
243*4882a593Smuzhiyun 	tmdsclk = clkrate * (49500000 / 1000);
244*4882a593Smuzhiyun 	rk628_i2c_read(aif->rk628, HDMI_RX_PDEC_ACR_CTS, &cts_decoded);
245*4882a593Smuzhiyun 	rk628_i2c_read(aif->rk628, HDMI_RX_PDEC_ACR_N, &n_decoded);
246*4882a593Smuzhiyun 	if (cts_decoded != 0) {
247*4882a593Smuzhiyun 		fs_audio = div_u64((tmdsclk * n_decoded), cts_decoded);
248*4882a593Smuzhiyun 		fs_audio /= 128;
249*4882a593Smuzhiyun 		fs_audio = div_u64(fs_audio + 50, 100);
250*4882a593Smuzhiyun 		fs_audio *= 100;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 	dev_dbg(aif->dev,
253*4882a593Smuzhiyun 		"%s: clkrate:%u tmdsclk:%llu, n_decoded:%u, cts_decoded:%u, fs_audio:%u\n",
254*4882a593Smuzhiyun 		__func__, clkrate, tmdsclk, n_decoded, cts_decoded, fs_audio);
255*4882a593Smuzhiyun 	if (!is_validfs(fs_audio))
256*4882a593Smuzhiyun 		fs_audio = 0;
257*4882a593Smuzhiyun 	return fs_audio;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun 
rk628_hdmirx_audio_clk_set_rate(struct rk628_audioinfo * aif,u32 rate)260*4882a593Smuzhiyun static void rk628_hdmirx_audio_clk_set_rate(struct rk628_audioinfo *aif, u32 rate)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s: %u to %u\n",
264*4882a593Smuzhiyun 		 __func__, aif->audio_state.hdmirx_aud_clkrate, rate);
265*4882a593Smuzhiyun 	rk628_clk_set_rate(aif->rk628, CGU_CLK_HDMIRX_AUD, rate);
266*4882a593Smuzhiyun 	aif->audio_state.hdmirx_aud_clkrate = rate;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun 
rk628_hdmirx_audio_clk_inc_rate(struct rk628_audioinfo * aif,int dis)269*4882a593Smuzhiyun static void rk628_hdmirx_audio_clk_inc_rate(struct rk628_audioinfo *aif, int dis)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun 	u32 hdmirx_aud_clkrate = aif->audio_state.hdmirx_aud_clkrate + dis;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s: %u to %u\n",
274*4882a593Smuzhiyun 		 __func__, aif->audio_state.hdmirx_aud_clkrate, hdmirx_aud_clkrate);
275*4882a593Smuzhiyun 	rk628_clk_set_rate(aif->rk628, CGU_CLK_HDMIRX_AUD, hdmirx_aud_clkrate);
276*4882a593Smuzhiyun 	aif->audio_state.hdmirx_aud_clkrate = hdmirx_aud_clkrate;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
rk628_hdmirx_audio_set_fs(struct rk628_audioinfo * aif,u32 fs_audio)279*4882a593Smuzhiyun static void rk628_hdmirx_audio_set_fs(struct rk628_audioinfo *aif, u32 fs_audio)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	u32 hdmirx_aud_clkrate_t = fs_audio*128;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s: %u to %u with fs %u\n", __func__,
284*4882a593Smuzhiyun 		 aif->audio_state.hdmirx_aud_clkrate, hdmirx_aud_clkrate_t,
285*4882a593Smuzhiyun 		 fs_audio);
286*4882a593Smuzhiyun 	rk628_clk_set_rate(aif->rk628, CGU_CLK_HDMIRX_AUD, hdmirx_aud_clkrate_t);
287*4882a593Smuzhiyun 	aif->audio_state.hdmirx_aud_clkrate = hdmirx_aud_clkrate_t;
288*4882a593Smuzhiyun 	aif->audio_state.fs_audio = fs_audio;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
rk628_hdmirx_audio_enable(struct rk628_audioinfo * aif)291*4882a593Smuzhiyun static void rk628_hdmirx_audio_enable(struct rk628_audioinfo *aif)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun 	u32 fifo_ints;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	rk628_i2c_read(aif->rk628, HDMI_RX_AUD_FIFO_ISTS, &fifo_ints);
296*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s fifo ints %#x\n", __func__, fifo_ints);
297*4882a593Smuzhiyun 	if ((fifo_ints & 0x18) == 0x18)
298*4882a593Smuzhiyun 		rk628_hdmirx_audio_fifo_initd(aif);
299*4882a593Smuzhiyun 	else if (fifo_ints & 0x18)
300*4882a593Smuzhiyun 		rk628_hdmirx_audio_fifo_init(aif);
301*4882a593Smuzhiyun 	rk628_i2c_update_bits(aif->rk628, HDMI_RX_DMI_DISABLE_IF,
302*4882a593Smuzhiyun 			      AUD_ENABLE_MASK, AUD_ENABLE(1));
303*4882a593Smuzhiyun 	aif->audio_state.audio_enable = true;
304*4882a593Smuzhiyun 	aif->fifo_ints_en = true;
305*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_IEN_SET,
306*4882a593Smuzhiyun 			AFIF_OVERFL_ISTS | AFIF_UNDERFL_ISTS);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun 
rk628_csi_delayed_work_audio(struct work_struct * work)309*4882a593Smuzhiyun static void rk628_csi_delayed_work_audio(struct work_struct *work)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun 	struct delayed_work *dwork = to_delayed_work(work);
312*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = container_of(dwork, struct rk628_audioinfo,
313*4882a593Smuzhiyun 						   delayed_work_audio);
314*4882a593Smuzhiyun 	struct rk628_audiostate *audio_state = &aif->audio_state;
315*4882a593Smuzhiyun 	u32 fs_audio;
316*4882a593Smuzhiyun 	int cur_state, init_state, pre_state;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	init_state = audio_state->init_state;
319*4882a593Smuzhiyun 	pre_state = audio_state->pre_state;
320*4882a593Smuzhiyun 	fs_audio = _rk628_hdmirx_audio_fs(aif);
321*4882a593Smuzhiyun 	if (!is_validfs(fs_audio)) {
322*4882a593Smuzhiyun 		dev_dbg(aif->dev, "%s: no supported fs(%u)\n", __func__, fs_audio);
323*4882a593Smuzhiyun 		goto exit;
324*4882a593Smuzhiyun 	}
325*4882a593Smuzhiyun 	if (!audio_state->audio_enable) {
326*4882a593Smuzhiyun 		rk628_hdmirx_audio_set_fs(aif, fs_audio);
327*4882a593Smuzhiyun 		rk628_hdmirx_audio_enable(aif);
328*4882a593Smuzhiyun 		goto exit;
329*4882a593Smuzhiyun 	}
330*4882a593Smuzhiyun 	if (abs(fs_audio - audio_state->fs_audio) > 1000)
331*4882a593Smuzhiyun 		rk628_hdmirx_audio_set_fs(aif, fs_audio);
332*4882a593Smuzhiyun 	rk628_i2c_read(aif->rk628, HDMI_RX_AUD_FIFO_FILLSTS1, &cur_state);
333*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s: HDMI_RX_AUD_FIFO_FILLSTS1:%#x, single offset:%d, total offset:%d\n",
334*4882a593Smuzhiyun 		 __func__, cur_state, cur_state - pre_state, cur_state - init_state);
335*4882a593Smuzhiyun 	if (cur_state != 0)
336*4882a593Smuzhiyun 		aif->audio_present = true;
337*4882a593Smuzhiyun 	else
338*4882a593Smuzhiyun 		aif->audio_present = false;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	if ((cur_state - init_state) > 16 && (cur_state - pre_state) > 0)
341*4882a593Smuzhiyun 		rk628_hdmirx_audio_clk_inc_rate(aif, 10);
342*4882a593Smuzhiyun 	else if ((cur_state != 0) && (cur_state - init_state) < -16 && (cur_state - pre_state) < 0)
343*4882a593Smuzhiyun 		rk628_hdmirx_audio_clk_inc_rate(aif, -10);
344*4882a593Smuzhiyun 	audio_state->pre_state = cur_state;
345*4882a593Smuzhiyun exit:
346*4882a593Smuzhiyun 	schedule_delayed_work(&aif->delayed_work_audio, msecs_to_jiffies(1000));
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
rk628_csi_delayed_work_audio_rate_change(struct work_struct * work)350*4882a593Smuzhiyun static void rk628_csi_delayed_work_audio_rate_change(struct work_struct *work)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun 	u32 fifo_fillsts;
353*4882a593Smuzhiyun 	u32 fs_audio;
354*4882a593Smuzhiyun 	struct delayed_work *dwork = to_delayed_work(work);
355*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = container_of(dwork, struct rk628_audioinfo,
356*4882a593Smuzhiyun 						   delayed_work_audio_rate_change);
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	mutex_lock(aif->confctl_mutex);
359*4882a593Smuzhiyun 	fs_audio = _rk628_hdmirx_audio_fs(aif);
360*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s get audio fs %u\n", __func__, fs_audio);
361*4882a593Smuzhiyun 	if (aif->audio_state.ctsn_flag == (ACR_N_CHG_ICLR | ACR_CTS_CHG_ICLR)) {
362*4882a593Smuzhiyun 		aif->audio_state.ctsn_flag = 0;
363*4882a593Smuzhiyun 		if (is_validfs(fs_audio)) {
364*4882a593Smuzhiyun 			rk628_hdmirx_audio_set_fs(aif, fs_audio);
365*4882a593Smuzhiyun 			/* We start audio work after recieveing cts n interrupt */
366*4882a593Smuzhiyun 			rk628_hdmirx_audio_enable(aif);
367*4882a593Smuzhiyun 		} else {
368*4882a593Smuzhiyun 			dev_dbg(aif->dev, "%s invalid fs when ctsn updating\n", __func__);
369*4882a593Smuzhiyun 		}
370*4882a593Smuzhiyun 		schedule_delayed_work(&aif->delayed_work_audio, msecs_to_jiffies(1000));
371*4882a593Smuzhiyun 	}
372*4882a593Smuzhiyun 	if (aif->audio_state.fifo_int) {
373*4882a593Smuzhiyun 		aif->audio_state.fifo_int = false;
374*4882a593Smuzhiyun 		if (is_validfs(fs_audio))
375*4882a593Smuzhiyun 			rk628_hdmirx_audio_set_fs(aif, fs_audio);
376*4882a593Smuzhiyun 		rk628_i2c_read(aif->rk628, HDMI_RX_AUD_FIFO_FILLSTS1, &fifo_fillsts);
377*4882a593Smuzhiyun 		if (!fifo_fillsts) {
378*4882a593Smuzhiyun 			dev_dbg(aif->dev, "%s underflow after overflow\n", __func__);
379*4882a593Smuzhiyun 			rk628_hdmirx_audio_fifo_initd(aif);
380*4882a593Smuzhiyun 		} else {
381*4882a593Smuzhiyun 			dev_dbg(aif->dev, "%s overflow after underflow\n", __func__);
382*4882a593Smuzhiyun 			rk628_hdmirx_audio_fifo_initd(aif);
383*4882a593Smuzhiyun 		}
384*4882a593Smuzhiyun 	}
385*4882a593Smuzhiyun 	mutex_unlock(aif->confctl_mutex);
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun 
rk628_hdmirx_audioinfo_alloc(struct device * dev,struct mutex * confctl_mutex,struct rk628 * rk628,bool en)388*4882a593Smuzhiyun HAUDINFO rk628_hdmirx_audioinfo_alloc(struct device *dev,
389*4882a593Smuzhiyun 				      struct mutex *confctl_mutex,
390*4882a593Smuzhiyun 				      struct rk628 *rk628,
391*4882a593Smuzhiyun 				      bool en)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun 	struct rk628_audioinfo *aif;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	aif = devm_kzalloc(dev, sizeof(*aif), GFP_KERNEL);
396*4882a593Smuzhiyun 	if (!aif)
397*4882a593Smuzhiyun 		return NULL;
398*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&aif->delayed_work_audio_rate_change,
399*4882a593Smuzhiyun 			  rk628_csi_delayed_work_audio_rate_change);
400*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&aif->delayed_work_audio,
401*4882a593Smuzhiyun 			  rk628_csi_delayed_work_audio);
402*4882a593Smuzhiyun 	aif->confctl_mutex = confctl_mutex;
403*4882a593Smuzhiyun 	aif->rk628 = rk628;
404*4882a593Smuzhiyun 	aif->i2s_enabled_default = en;
405*4882a593Smuzhiyun 	aif->dev = dev;
406*4882a593Smuzhiyun 	return aif;
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_hdmirx_audioinfo_alloc);
409*4882a593Smuzhiyun 
rk628_hdmirx_audio_cancel_work_audio(HAUDINFO info,bool sync)410*4882a593Smuzhiyun void rk628_hdmirx_audio_cancel_work_audio(HAUDINFO info, bool sync)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	if (sync)
415*4882a593Smuzhiyun 		cancel_delayed_work_sync(&aif->delayed_work_audio);
416*4882a593Smuzhiyun 	else
417*4882a593Smuzhiyun 		cancel_delayed_work(&aif->delayed_work_audio);
418*4882a593Smuzhiyun }
419*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_hdmirx_audio_cancel_work_audio);
420*4882a593Smuzhiyun 
rk628_hdmirx_audio_cancel_work_rate_change(HAUDINFO info,bool sync)421*4882a593Smuzhiyun void rk628_hdmirx_audio_cancel_work_rate_change(HAUDINFO info, bool sync)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	if (sync)
426*4882a593Smuzhiyun 		cancel_delayed_work_sync(&aif->delayed_work_audio_rate_change);
427*4882a593Smuzhiyun 	else
428*4882a593Smuzhiyun 		cancel_delayed_work(&aif->delayed_work_audio_rate_change);
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_hdmirx_audio_cancel_work_rate_change);
431*4882a593Smuzhiyun 
rk628_hdmirx_audio_destroy(HAUDINFO info)432*4882a593Smuzhiyun void rk628_hdmirx_audio_destroy(HAUDINFO info)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	if (!aif)
437*4882a593Smuzhiyun 		return;
438*4882a593Smuzhiyun 	rk628_hdmirx_audio_cancel_work_audio(aif, true);
439*4882a593Smuzhiyun 	rk628_hdmirx_audio_cancel_work_rate_change(aif, true);
440*4882a593Smuzhiyun 	aif->confctl_mutex = NULL;
441*4882a593Smuzhiyun 	aif->rk628 = NULL;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_hdmirx_audio_destroy);
444*4882a593Smuzhiyun 
rk628_hdmirx_audio_present(HAUDINFO info)445*4882a593Smuzhiyun bool rk628_hdmirx_audio_present(HAUDINFO info)
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	if (!aif)
450*4882a593Smuzhiyun 		return false;
451*4882a593Smuzhiyun 	return aif->audio_present;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_hdmirx_audio_present);
454*4882a593Smuzhiyun 
rk628_hdmirx_audio_fs(HAUDINFO info)455*4882a593Smuzhiyun int rk628_hdmirx_audio_fs(HAUDINFO info)
456*4882a593Smuzhiyun {
457*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	if (!aif)
460*4882a593Smuzhiyun 		return 0;
461*4882a593Smuzhiyun 	return aif->audio_state.fs_audio;
462*4882a593Smuzhiyun }
463*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_hdmirx_audio_fs);
464*4882a593Smuzhiyun 
rk628_hdmirx_audio_i2s_ctrl(HAUDINFO info,bool enable)465*4882a593Smuzhiyun void rk628_hdmirx_audio_i2s_ctrl(HAUDINFO info, bool enable)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	if (enable == aif->i2s_enabled)
470*4882a593Smuzhiyun 		return;
471*4882a593Smuzhiyun 	if (enable) {
472*4882a593Smuzhiyun 		rk628_i2c_write(aif->rk628, HDMI_RX_AUD_SAO_CTRL,
473*4882a593Smuzhiyun 				I2S_LPCM_BPCUV(0) |
474*4882a593Smuzhiyun 				I2S_32_16(1));
475*4882a593Smuzhiyun 	} else {
476*4882a593Smuzhiyun 		rk628_i2c_write(aif->rk628, HDMI_RX_AUD_SAO_CTRL,
477*4882a593Smuzhiyun 				I2S_LPCM_BPCUV(0) |
478*4882a593Smuzhiyun 				I2S_32_16(1) |
479*4882a593Smuzhiyun 				I2S_ENABLE_BITS(0x3f));
480*4882a593Smuzhiyun 	}
481*4882a593Smuzhiyun 	aif->i2s_enabled = enable;
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_hdmirx_audio_i2s_ctrl);
484*4882a593Smuzhiyun 
rk628_hdmirx_audio_setup(HAUDINFO info)485*4882a593Smuzhiyun void rk628_hdmirx_audio_setup(HAUDINFO info)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
488*4882a593Smuzhiyun 	u32 audio_pll_n, audio_pll_cts;
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s: setup audio\n", __func__);
491*4882a593Smuzhiyun 	audio_pll_n = 5644;
492*4882a593Smuzhiyun 	audio_pll_cts = 148500;
493*4882a593Smuzhiyun 	aif->audio_state.ctsn_flag = 0;
494*4882a593Smuzhiyun 	aif->audio_state.fs_audio = 0;
495*4882a593Smuzhiyun 	aif->audio_state.pre_state = 0;
496*4882a593Smuzhiyun 	aif->audio_state.init_state = INIT_FIFO_STATE*4;
497*4882a593Smuzhiyun 	aif->audio_state.fifo_int = false;
498*4882a593Smuzhiyun 	aif->audio_state.audio_enable = false;
499*4882a593Smuzhiyun 	aif->fifo_ints_en = false;
500*4882a593Smuzhiyun 	aif->ctsn_ints_en = false;
501*4882a593Smuzhiyun 	aif->i2s_enabled = false;
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	rk628_hdmirx_audio_clk_set_rate(aif, 5644800);
504*4882a593Smuzhiyun 	/* manual aud CTS */
505*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUDPLL_GEN_CTS, audio_pll_cts);
506*4882a593Smuzhiyun 	/* manual aud N */
507*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUDPLL_GEN_N, audio_pll_n);
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	/* aud CTS N en manual */
510*4882a593Smuzhiyun 	rk628_i2c_update_bits(aif->rk628, HDMI_RX_AUD_CLK_CTRL,
511*4882a593Smuzhiyun 			CTS_N_REF_MASK, CTS_N_REF(1));
512*4882a593Smuzhiyun 	/* aud pll ctrl */
513*4882a593Smuzhiyun 	rk628_i2c_update_bits(aif->rk628, HDMI_RX_AUD_PLL_CTRL,
514*4882a593Smuzhiyun 			PLL_LOCK_TOGGLE_DIV_MASK, PLL_LOCK_TOGGLE_DIV(0));
515*4882a593Smuzhiyun 	rk628_i2c_update_bits(aif->rk628, HDMI_RX_AUD_FIFO_TH,
516*4882a593Smuzhiyun 		AFIF_TH_START_MASK |
517*4882a593Smuzhiyun 		AFIF_TH_MAX_MASK |
518*4882a593Smuzhiyun 		AFIF_TH_MIN_MASK,
519*4882a593Smuzhiyun 		AFIF_TH_START(64) |
520*4882a593Smuzhiyun 		AFIF_TH_MAX(8) |
521*4882a593Smuzhiyun 		AFIF_TH_MIN(8));
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	/* AUTO_VMUTE */
524*4882a593Smuzhiyun 	rk628_i2c_update_bits(aif->rk628, HDMI_RX_AUD_FIFO_CTRL,
525*4882a593Smuzhiyun 			AFIF_SUBPACKET_DESEL_MASK |
526*4882a593Smuzhiyun 			AFIF_SUBPACKETS_MASK,
527*4882a593Smuzhiyun 			AFIF_SUBPACKET_DESEL(0) |
528*4882a593Smuzhiyun 			AFIF_SUBPACKETS(1));
529*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_SAO_CTRL,
530*4882a593Smuzhiyun 			I2S_LPCM_BPCUV(0) |
531*4882a593Smuzhiyun 			I2S_32_16(1)|
532*4882a593Smuzhiyun 			(aif->i2s_enabled_default ? 0 : I2S_ENABLE_BITS(0x3f)));
533*4882a593Smuzhiyun 	aif->i2s_enabled = aif->i2s_enabled_default;
534*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_MUTE_CTRL,
535*4882a593Smuzhiyun 			APPLY_INT_MUTE(0)	|
536*4882a593Smuzhiyun 			APORT_SHDW_CTRL(3)	|
537*4882a593Smuzhiyun 			AUTO_ACLK_MUTE(2)	|
538*4882a593Smuzhiyun 			AUD_MUTE_SPEED(1)	|
539*4882a593Smuzhiyun 			AUD_AVMUTE_EN(1)	|
540*4882a593Smuzhiyun 			AUD_MUTE_SEL(0)		|
541*4882a593Smuzhiyun 			AUD_MUTE_MODE(1));
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_PAO_CTRL,
544*4882a593Smuzhiyun 			PAO_RATE(0));
545*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_CHEXTR_CTRL,
546*4882a593Smuzhiyun 			AUD_LAYOUT_CTRL(1));
547*4882a593Smuzhiyun 	aif->ctsn_ints_en = true;
548*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_PDEC_IEN_SET, ACR_N_CHG_ICLR | ACR_CTS_CHG_ICLR);
549*4882a593Smuzhiyun 	/* audio detect */
550*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_PDEC_AUDIODET_CTRL,
551*4882a593Smuzhiyun 			AUDIODET_THRESHOLD(0));
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_hdmirx_audio_setup);
554*4882a593Smuzhiyun 
rk628_audio_fifoints_enabled(HAUDINFO info)555*4882a593Smuzhiyun bool rk628_audio_fifoints_enabled(HAUDINFO info)
556*4882a593Smuzhiyun {
557*4882a593Smuzhiyun 	return ((struct rk628_audioinfo *)info)->fifo_ints_en;
558*4882a593Smuzhiyun }
559*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_audio_fifoints_enabled);
560*4882a593Smuzhiyun 
rk628_audio_ctsnints_enabled(HAUDINFO info)561*4882a593Smuzhiyun bool rk628_audio_ctsnints_enabled(HAUDINFO info)
562*4882a593Smuzhiyun {
563*4882a593Smuzhiyun 	return ((struct rk628_audioinfo *)info)->ctsn_ints_en;
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_audio_ctsnints_enabled);
566*4882a593Smuzhiyun 
rk628_csi_isr_ctsn(HAUDINFO info,u32 pdec_ints)567*4882a593Smuzhiyun void rk628_csi_isr_ctsn(HAUDINFO info, u32 pdec_ints)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
570*4882a593Smuzhiyun 	u32 ctsn_mask = ACR_N_CHG_ICLR | ACR_CTS_CHG_ICLR;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s: pdec_ints:%#x\n", __func__, pdec_ints);
573*4882a593Smuzhiyun 	/* cts & n both need update but maybe come diff int */
574*4882a593Smuzhiyun 	if (pdec_ints & ACR_N_CHG_ICLR)
575*4882a593Smuzhiyun 		aif->audio_state.ctsn_flag |= ACR_N_CHG_ICLR;
576*4882a593Smuzhiyun 	if (pdec_ints & ACR_CTS_CHG_ICLR)
577*4882a593Smuzhiyun 		aif->audio_state.ctsn_flag |= ACR_CTS_CHG_ICLR;
578*4882a593Smuzhiyun 	if (aif->audio_state.ctsn_flag == ctsn_mask) {
579*4882a593Smuzhiyun 		dev_dbg(aif->dev, "%s: ctsn updated, disable ctsn int\n", __func__);
580*4882a593Smuzhiyun 		rk628_i2c_write(aif->rk628, HDMI_RX_PDEC_IEN_CLR, ctsn_mask);
581*4882a593Smuzhiyun 		aif->ctsn_ints_en = false;
582*4882a593Smuzhiyun 		schedule_delayed_work(&aif->delayed_work_audio_rate_change, 0);
583*4882a593Smuzhiyun 	}
584*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_PDEC_ICLR, pdec_ints & ctsn_mask);
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_csi_isr_ctsn);
587*4882a593Smuzhiyun 
rk628_csi_isr_fifoints(HAUDINFO info,u32 fifo_ints)588*4882a593Smuzhiyun void rk628_csi_isr_fifoints(HAUDINFO info, u32 fifo_ints)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun 	struct rk628_audioinfo *aif = (struct rk628_audioinfo *)info;
591*4882a593Smuzhiyun 	u32 fifo_mask = AFIF_OVERFL_ISTS | AFIF_UNDERFL_ISTS;
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	dev_dbg(aif->dev, "%s: fifo_ints:%#x\n", __func__, fifo_ints);
594*4882a593Smuzhiyun 	/* cts & n both need update but maybe come diff int */
595*4882a593Smuzhiyun 	if (fifo_ints & AFIF_OVERFL_ISTS) {
596*4882a593Smuzhiyun 		dev_dbg(aif->dev, "%s: Audio FIFO overflow\n", __func__);
597*4882a593Smuzhiyun 		aif->audio_state.fifo_flag |= AFIF_OVERFL_ISTS;
598*4882a593Smuzhiyun 	}
599*4882a593Smuzhiyun 	if (fifo_ints & AFIF_UNDERFL_ISTS) {
600*4882a593Smuzhiyun 		dev_dbg(aif->dev, "%s: Audio FIFO underflow\n", __func__);
601*4882a593Smuzhiyun 		aif->audio_state.fifo_flag |= AFIF_UNDERFL_ISTS;
602*4882a593Smuzhiyun 	}
603*4882a593Smuzhiyun 	if (aif->audio_state.fifo_flag == fifo_mask) {
604*4882a593Smuzhiyun 		aif->audio_state.fifo_int = true;
605*4882a593Smuzhiyun 		aif->audio_state.fifo_flag = 0;
606*4882a593Smuzhiyun 		schedule_delayed_work(&aif->delayed_work_audio_rate_change, 0);
607*4882a593Smuzhiyun 	}
608*4882a593Smuzhiyun 	rk628_i2c_write(aif->rk628, HDMI_RX_AUD_FIFO_ICLR, fifo_ints & fifo_mask);
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_csi_isr_fifoints);
611*4882a593Smuzhiyun 
rk628_is_avi_ready(struct rk628 * rk628,bool avi_rcv_rdy)612*4882a593Smuzhiyun int rk628_is_avi_ready(struct rk628 *rk628, bool avi_rcv_rdy)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun 	u8 i;
615*4882a593Smuzhiyun 	u32 val, avi_pb = 0;
616*4882a593Smuzhiyun 	u8 cnt = 0, max_cnt = 2;
617*4882a593Smuzhiyun 	u32 hdcp_ctrl_val = 0;
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	rk628_i2c_read(rk628, HDMI_RX_HDCP_CTRL, &val);
620*4882a593Smuzhiyun 	if ((val & HDCP_ENABLE_MASK))
621*4882a593Smuzhiyun 		max_cnt = 5;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	for (i = 0; i < 100; i++) {
624*4882a593Smuzhiyun 		rk628_i2c_read(rk628, HDMI_RX_PDEC_AVI_PB, &val);
625*4882a593Smuzhiyun 		dev_info(rk628->dev, "%s PDEC_AVI_PB:%#x, avi_rcv_rdy:%d\n",
626*4882a593Smuzhiyun 			 __func__, val, avi_rcv_rdy);
627*4882a593Smuzhiyun 		if (i > 30 && !(hdcp_ctrl_val & 0x400)) {
628*4882a593Smuzhiyun 			rk628_i2c_read(rk628, HDMI_RX_HDCP_CTRL, &hdcp_ctrl_val);
629*4882a593Smuzhiyun 			/* force hdcp avmute */
630*4882a593Smuzhiyun 			hdcp_ctrl_val |= 0x400;
631*4882a593Smuzhiyun 			rk628_i2c_write(rk628, HDMI_RX_HDCP_CTRL, hdcp_ctrl_val);
632*4882a593Smuzhiyun 		}
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 		if (val && val == avi_pb && avi_rcv_rdy) {
635*4882a593Smuzhiyun 			if (++cnt >= max_cnt)
636*4882a593Smuzhiyun 				break;
637*4882a593Smuzhiyun 		} else {
638*4882a593Smuzhiyun 			cnt = 0;
639*4882a593Smuzhiyun 			avi_pb = val;
640*4882a593Smuzhiyun 		}
641*4882a593Smuzhiyun 		msleep(30);
642*4882a593Smuzhiyun 	}
643*4882a593Smuzhiyun 	if (cnt < max_cnt)
644*4882a593Smuzhiyun 		return 0;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	return 1;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun EXPORT_SYMBOL(rk628_is_avi_ready);
649