xref: /linux/drivers/gpu/drm/i2c/tda998x_drv.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e7792ce2SRob Clark /*
3e7792ce2SRob Clark  * Copyright (C) 2012 Texas Instruments
4e7792ce2SRob Clark  * Author: Rob Clark <robdclark@gmail.com>
5e7792ce2SRob Clark  */
6e7792ce2SRob Clark 
7c707c361SRussell King #include <linux/component.h>
87e8675f0SRussell King #include <linux/gpio/consumer.h>
9893c3e53SRussell King #include <linux/hdmi.h>
10a204f974SVille Syrjälä #include <linux/i2c.h>
11e7792ce2SRob Clark #include <linux/module.h>
127e8675f0SRussell King #include <linux/platform_data/tda9950.h>
1312473b7dSJean-Francois Moine #include <linux/irq.h>
14f0b33b28SJean-Francois Moine #include <sound/asoundef.h>
157e567624SJyri Sarha #include <sound/hdmi-codec.h>
16e7792ce2SRob Clark 
179736e988SLiviu Dudau (ARM) #include <drm/drm_atomic_helper.h>
18ee68c743SBoris Brezillon #include <drm/drm_bridge.h>
19e7792ce2SRob Clark #include <drm/drm_edid.h>
205dbcf319SRussell King #include <drm/drm_of.h>
215c8a5f1dSSam Ravnborg #include <drm/drm_print.h>
22fcd70cd3SDaniel Vetter #include <drm/drm_probe_helper.h>
23a1170f90SThomas Zimmermann #include <drm/drm_simple_kms_helper.h>
24c4c11dd1SRussell King #include <drm/i2c/tda998x.h>
25e7792ce2SRob Clark 
267e8675f0SRussell King #include <media/cec-notifier.h>
277e8675f0SRussell King 
28e7792ce2SRob Clark #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
29e7792ce2SRob Clark 
3071689160SRussell King enum {
3171689160SRussell King 	AUDIO_ROUTE_I2S,
3271689160SRussell King 	AUDIO_ROUTE_SPDIF,
3371689160SRussell King 	AUDIO_ROUTE_NUM
347e567624SJyri Sarha };
357e567624SJyri Sarha 
3626f7bf12SRussell King struct tda998x_audio_route {
3726f7bf12SRussell King 	u8 ena_aclk;
3826f7bf12SRussell King 	u8 mux_ap;
3926f7bf12SRussell King 	u8 aip_clksel;
4026f7bf12SRussell King };
4126f7bf12SRussell King 
422e9943aaSRussell King struct tda998x_audio_settings {
4326f7bf12SRussell King 	const struct tda998x_audio_route *route;
44125a4f93SRussell King 	struct hdmi_audio_infoframe cea;
45125a4f93SRussell King 	unsigned int sample_rate;
46125a4f93SRussell King 	u8 status[5];
4782642ab7SRussell King 	u8 ena_ap;
48935b9ca3SRussell King 	u8 i2s_format;
49a03a915bSRussell King 	u8 cts_n;
50e7792ce2SRob Clark };
51e7792ce2SRob Clark 
52e7792ce2SRob Clark struct tda998x_priv {
53e7792ce2SRob Clark 	struct i2c_client *cec;
542f7f730aSJean-Francois Moine 	struct i2c_client *hdmi;
55ed9a8426SJean-Francois Moine 	struct mutex mutex;
56e66e03abSRussell King 	u16 rev;
5714e5b588SRussell King 	u8 cec_addr;
58e66e03abSRussell King 	u8 current_page;
593cb43378SRussell King 	bool is_on;
60896a4130SRussell King 	bool supports_infoframes;
618f3f21f6SRussell King 	bool sink_has_audio;
62fcc22c5fSRussell King 	enum hdmi_quantization_range rgb_quant_range;
635e74c22cSRussell King 	u8 vip_cntrl_0;
645e74c22cSRussell King 	u8 vip_cntrl_1;
655e74c22cSRussell King 	u8 vip_cntrl_2;
66319e658cSRussell King 	unsigned long tmds_clock;
672e9943aaSRussell King 	struct tda998x_audio_settings audio;
6812473b7dSJean-Francois Moine 
697e567624SJyri Sarha 	struct platform_device *audio_pdev;
707e567624SJyri Sarha 	struct mutex audio_mutex;
717e567624SJyri Sarha 
727e8675f0SRussell King 	struct mutex edid_mutex;
7312473b7dSJean-Francois Moine 	wait_queue_head_t wq_edid;
7412473b7dSJean-Francois Moine 	volatile int wq_edid_wait;
750fc6f44dSRussell King 
760fc6f44dSRussell King 	struct work_struct detect_work;
770fc6f44dSRussell King 	struct timer_list edid_delay_timer;
780fc6f44dSRussell King 	wait_queue_head_t edid_delay_waitq;
790fc6f44dSRussell King 	bool edid_delay_active;
8078e401f9SRussell King 
8178e401f9SRussell King 	struct drm_encoder encoder;
8230bd8b86SRussell King 	struct drm_bridge bridge;
83eed64b59SRussell King 	struct drm_connector connector;
847e567624SJyri Sarha 
8571689160SRussell King 	u8 audio_port_enable[AUDIO_ROUTE_NUM];
867e8675f0SRussell King 	struct tda9950_glue cec_glue;
877e8675f0SRussell King 	struct gpio_desc *calib;
887e8675f0SRussell King 	struct cec_notifier *cec_notify;
89e7792ce2SRob Clark };
90e7792ce2SRob Clark 
919525c4ddSRussell King #define conn_to_tda998x_priv(x) \
929525c4ddSRussell King 	container_of(x, struct tda998x_priv, connector)
939525c4ddSRussell King #define enc_to_tda998x_priv(x) \
949525c4ddSRussell King 	container_of(x, struct tda998x_priv, encoder)
9530bd8b86SRussell King #define bridge_to_tda998x_priv(x) \
9630bd8b86SRussell King 	container_of(x, struct tda998x_priv, bridge)
979525c4ddSRussell King 
98e7792ce2SRob Clark /* The TDA9988 series of devices use a paged register scheme.. to simplify
99e7792ce2SRob Clark  * things we encode the page # in upper bits of the register #.  To read/
100e7792ce2SRob Clark  * write a given register, we need to make sure CURPAGE register is set
101e7792ce2SRob Clark  * appropriately.  Which implies reads/writes are not atomic.  Fun!
102e7792ce2SRob Clark  */
103e7792ce2SRob Clark 
104e7792ce2SRob Clark #define REG(page, addr) (((page) << 8) | (addr))
105e7792ce2SRob Clark #define REG2ADDR(reg)   ((reg) & 0xff)
106e7792ce2SRob Clark #define REG2PAGE(reg)   (((reg) >> 8) & 0xff)
107e7792ce2SRob Clark 
108e7792ce2SRob Clark #define REG_CURPAGE               0xff                /* write */
109e7792ce2SRob Clark 
110e7792ce2SRob Clark 
111e7792ce2SRob Clark /* Page 00h: General Control */
112e7792ce2SRob Clark #define REG_VERSION_LSB           REG(0x00, 0x00)     /* read */
113e7792ce2SRob Clark #define REG_MAIN_CNTRL0           REG(0x00, 0x01)     /* read/write */
114e7792ce2SRob Clark # define MAIN_CNTRL0_SR           (1 << 0)
115e7792ce2SRob Clark # define MAIN_CNTRL0_DECS         (1 << 1)
116e7792ce2SRob Clark # define MAIN_CNTRL0_DEHS         (1 << 2)
117e7792ce2SRob Clark # define MAIN_CNTRL0_CECS         (1 << 3)
118e7792ce2SRob Clark # define MAIN_CNTRL0_CEHS         (1 << 4)
119e7792ce2SRob Clark # define MAIN_CNTRL0_SCALER       (1 << 7)
120e7792ce2SRob Clark #define REG_VERSION_MSB           REG(0x00, 0x02)     /* read */
121e7792ce2SRob Clark #define REG_SOFTRESET             REG(0x00, 0x0a)     /* write */
122e7792ce2SRob Clark # define SOFTRESET_AUDIO          (1 << 0)
123e7792ce2SRob Clark # define SOFTRESET_I2C_MASTER     (1 << 1)
124e7792ce2SRob Clark #define REG_DDC_DISABLE           REG(0x00, 0x0b)     /* read/write */
125e7792ce2SRob Clark #define REG_CCLK_ON               REG(0x00, 0x0c)     /* read/write */
126e7792ce2SRob Clark #define REG_I2C_MASTER            REG(0x00, 0x0d)     /* read/write */
127e7792ce2SRob Clark # define I2C_MASTER_DIS_MM        (1 << 0)
128e7792ce2SRob Clark # define I2C_MASTER_DIS_FILT      (1 << 1)
129e7792ce2SRob Clark # define I2C_MASTER_APP_STRT_LAT  (1 << 2)
130c4c11dd1SRussell King #define REG_FEAT_POWERDOWN        REG(0x00, 0x0e)     /* read/write */
1319476ed2eSRussell King # define FEAT_POWERDOWN_PREFILT   BIT(0)
1329476ed2eSRussell King # define FEAT_POWERDOWN_CSC       BIT(1)
133c4c11dd1SRussell King # define FEAT_POWERDOWN_SPDIF     (1 << 3)
134e7792ce2SRob Clark #define REG_INT_FLAGS_0           REG(0x00, 0x0f)     /* read/write */
135e7792ce2SRob Clark #define REG_INT_FLAGS_1           REG(0x00, 0x10)     /* read/write */
136e7792ce2SRob Clark #define REG_INT_FLAGS_2           REG(0x00, 0x11)     /* read/write */
137e7792ce2SRob Clark # define INT_FLAGS_2_EDID_BLK_RD  (1 << 1)
138c4c11dd1SRussell King #define REG_ENA_ACLK              REG(0x00, 0x16)     /* read/write */
139e7792ce2SRob Clark #define REG_ENA_VP_0              REG(0x00, 0x18)     /* read/write */
140e7792ce2SRob Clark #define REG_ENA_VP_1              REG(0x00, 0x19)     /* read/write */
141e7792ce2SRob Clark #define REG_ENA_VP_2              REG(0x00, 0x1a)     /* read/write */
142e7792ce2SRob Clark #define REG_ENA_AP                REG(0x00, 0x1e)     /* read/write */
143e7792ce2SRob Clark #define REG_VIP_CNTRL_0           REG(0x00, 0x20)     /* write */
144e7792ce2SRob Clark # define VIP_CNTRL_0_MIRR_A       (1 << 7)
145e7792ce2SRob Clark # define VIP_CNTRL_0_SWAP_A(x)    (((x) & 7) << 4)
146e7792ce2SRob Clark # define VIP_CNTRL_0_MIRR_B       (1 << 3)
147e7792ce2SRob Clark # define VIP_CNTRL_0_SWAP_B(x)    (((x) & 7) << 0)
148e7792ce2SRob Clark #define REG_VIP_CNTRL_1           REG(0x00, 0x21)     /* write */
149e7792ce2SRob Clark # define VIP_CNTRL_1_MIRR_C       (1 << 7)
150e7792ce2SRob Clark # define VIP_CNTRL_1_SWAP_C(x)    (((x) & 7) << 4)
151e7792ce2SRob Clark # define VIP_CNTRL_1_MIRR_D       (1 << 3)
152e7792ce2SRob Clark # define VIP_CNTRL_1_SWAP_D(x)    (((x) & 7) << 0)
153e7792ce2SRob Clark #define REG_VIP_CNTRL_2           REG(0x00, 0x22)     /* write */
154e7792ce2SRob Clark # define VIP_CNTRL_2_MIRR_E       (1 << 7)
155e7792ce2SRob Clark # define VIP_CNTRL_2_SWAP_E(x)    (((x) & 7) << 4)
156e7792ce2SRob Clark # define VIP_CNTRL_2_MIRR_F       (1 << 3)
157e7792ce2SRob Clark # define VIP_CNTRL_2_SWAP_F(x)    (((x) & 7) << 0)
158e7792ce2SRob Clark #define REG_VIP_CNTRL_3           REG(0x00, 0x23)     /* write */
159e7792ce2SRob Clark # define VIP_CNTRL_3_X_TGL        (1 << 0)
160e7792ce2SRob Clark # define VIP_CNTRL_3_H_TGL        (1 << 1)
161e7792ce2SRob Clark # define VIP_CNTRL_3_V_TGL        (1 << 2)
162e7792ce2SRob Clark # define VIP_CNTRL_3_EMB          (1 << 3)
163e7792ce2SRob Clark # define VIP_CNTRL_3_SYNC_DE      (1 << 4)
164e7792ce2SRob Clark # define VIP_CNTRL_3_SYNC_HS      (1 << 5)
165e7792ce2SRob Clark # define VIP_CNTRL_3_DE_INT       (1 << 6)
166e7792ce2SRob Clark # define VIP_CNTRL_3_EDGE         (1 << 7)
167e7792ce2SRob Clark #define REG_VIP_CNTRL_4           REG(0x00, 0x24)     /* write */
168e7792ce2SRob Clark # define VIP_CNTRL_4_BLC(x)       (((x) & 3) << 0)
169e7792ce2SRob Clark # define VIP_CNTRL_4_BLANKIT(x)   (((x) & 3) << 2)
170e7792ce2SRob Clark # define VIP_CNTRL_4_CCIR656      (1 << 4)
171e7792ce2SRob Clark # define VIP_CNTRL_4_656_ALT      (1 << 5)
172e7792ce2SRob Clark # define VIP_CNTRL_4_TST_656      (1 << 6)
173e7792ce2SRob Clark # define VIP_CNTRL_4_TST_PAT      (1 << 7)
174e7792ce2SRob Clark #define REG_VIP_CNTRL_5           REG(0x00, 0x25)     /* write */
175e7792ce2SRob Clark # define VIP_CNTRL_5_CKCASE       (1 << 0)
176e7792ce2SRob Clark # define VIP_CNTRL_5_SP_CNT(x)    (((x) & 3) << 1)
177c4c11dd1SRussell King #define REG_MUX_AP                REG(0x00, 0x26)     /* read/write */
17810df1a95SJean-Francois Moine # define MUX_AP_SELECT_I2S	  0x64
17910df1a95SJean-Francois Moine # define MUX_AP_SELECT_SPDIF	  0x40
180bcb2481dSRussell King #define REG_MUX_VP_VIP_OUT        REG(0x00, 0x27)     /* read/write */
181e7792ce2SRob Clark #define REG_MAT_CONTRL            REG(0x00, 0x80)     /* write */
182e7792ce2SRob Clark # define MAT_CONTRL_MAT_SC(x)     (((x) & 3) << 0)
183e7792ce2SRob Clark # define MAT_CONTRL_MAT_BP        (1 << 2)
184e7792ce2SRob Clark #define REG_VIDFORMAT             REG(0x00, 0xa0)     /* write */
185e7792ce2SRob Clark #define REG_REFPIX_MSB            REG(0x00, 0xa1)     /* write */
186e7792ce2SRob Clark #define REG_REFPIX_LSB            REG(0x00, 0xa2)     /* write */
187e7792ce2SRob Clark #define REG_REFLINE_MSB           REG(0x00, 0xa3)     /* write */
188e7792ce2SRob Clark #define REG_REFLINE_LSB           REG(0x00, 0xa4)     /* write */
189e7792ce2SRob Clark #define REG_NPIX_MSB              REG(0x00, 0xa5)     /* write */
190e7792ce2SRob Clark #define REG_NPIX_LSB              REG(0x00, 0xa6)     /* write */
191e7792ce2SRob Clark #define REG_NLINE_MSB             REG(0x00, 0xa7)     /* write */
192e7792ce2SRob Clark #define REG_NLINE_LSB             REG(0x00, 0xa8)     /* write */
193e7792ce2SRob Clark #define REG_VS_LINE_STRT_1_MSB    REG(0x00, 0xa9)     /* write */
194e7792ce2SRob Clark #define REG_VS_LINE_STRT_1_LSB    REG(0x00, 0xaa)     /* write */
195e7792ce2SRob Clark #define REG_VS_PIX_STRT_1_MSB     REG(0x00, 0xab)     /* write */
196e7792ce2SRob Clark #define REG_VS_PIX_STRT_1_LSB     REG(0x00, 0xac)     /* write */
197e7792ce2SRob Clark #define REG_VS_LINE_END_1_MSB     REG(0x00, 0xad)     /* write */
198e7792ce2SRob Clark #define REG_VS_LINE_END_1_LSB     REG(0x00, 0xae)     /* write */
199e7792ce2SRob Clark #define REG_VS_PIX_END_1_MSB      REG(0x00, 0xaf)     /* write */
200e7792ce2SRob Clark #define REG_VS_PIX_END_1_LSB      REG(0x00, 0xb0)     /* write */
201088d61d1SSebastian Hesselbarth #define REG_VS_LINE_STRT_2_MSB    REG(0x00, 0xb1)     /* write */
202088d61d1SSebastian Hesselbarth #define REG_VS_LINE_STRT_2_LSB    REG(0x00, 0xb2)     /* write */
203e7792ce2SRob Clark #define REG_VS_PIX_STRT_2_MSB     REG(0x00, 0xb3)     /* write */
204e7792ce2SRob Clark #define REG_VS_PIX_STRT_2_LSB     REG(0x00, 0xb4)     /* write */
205088d61d1SSebastian Hesselbarth #define REG_VS_LINE_END_2_MSB     REG(0x00, 0xb5)     /* write */
206088d61d1SSebastian Hesselbarth #define REG_VS_LINE_END_2_LSB     REG(0x00, 0xb6)     /* write */
207e7792ce2SRob Clark #define REG_VS_PIX_END_2_MSB      REG(0x00, 0xb7)     /* write */
208e7792ce2SRob Clark #define REG_VS_PIX_END_2_LSB      REG(0x00, 0xb8)     /* write */
209e7792ce2SRob Clark #define REG_HS_PIX_START_MSB      REG(0x00, 0xb9)     /* write */
210e7792ce2SRob Clark #define REG_HS_PIX_START_LSB      REG(0x00, 0xba)     /* write */
211e7792ce2SRob Clark #define REG_HS_PIX_STOP_MSB       REG(0x00, 0xbb)     /* write */
212e7792ce2SRob Clark #define REG_HS_PIX_STOP_LSB       REG(0x00, 0xbc)     /* write */
213e7792ce2SRob Clark #define REG_VWIN_START_1_MSB      REG(0x00, 0xbd)     /* write */
214e7792ce2SRob Clark #define REG_VWIN_START_1_LSB      REG(0x00, 0xbe)     /* write */
215e7792ce2SRob Clark #define REG_VWIN_END_1_MSB        REG(0x00, 0xbf)     /* write */
216e7792ce2SRob Clark #define REG_VWIN_END_1_LSB        REG(0x00, 0xc0)     /* write */
217088d61d1SSebastian Hesselbarth #define REG_VWIN_START_2_MSB      REG(0x00, 0xc1)     /* write */
218088d61d1SSebastian Hesselbarth #define REG_VWIN_START_2_LSB      REG(0x00, 0xc2)     /* write */
219088d61d1SSebastian Hesselbarth #define REG_VWIN_END_2_MSB        REG(0x00, 0xc3)     /* write */
220088d61d1SSebastian Hesselbarth #define REG_VWIN_END_2_LSB        REG(0x00, 0xc4)     /* write */
221e7792ce2SRob Clark #define REG_DE_START_MSB          REG(0x00, 0xc5)     /* write */
222e7792ce2SRob Clark #define REG_DE_START_LSB          REG(0x00, 0xc6)     /* write */
223e7792ce2SRob Clark #define REG_DE_STOP_MSB           REG(0x00, 0xc7)     /* write */
224e7792ce2SRob Clark #define REG_DE_STOP_LSB           REG(0x00, 0xc8)     /* write */
225e7792ce2SRob Clark #define REG_TBG_CNTRL_0           REG(0x00, 0xca)     /* write */
226088d61d1SSebastian Hesselbarth # define TBG_CNTRL_0_TOP_TGL      (1 << 0)
227088d61d1SSebastian Hesselbarth # define TBG_CNTRL_0_TOP_SEL      (1 << 1)
228088d61d1SSebastian Hesselbarth # define TBG_CNTRL_0_DE_EXT       (1 << 2)
229088d61d1SSebastian Hesselbarth # define TBG_CNTRL_0_TOP_EXT      (1 << 3)
230e7792ce2SRob Clark # define TBG_CNTRL_0_FRAME_DIS    (1 << 5)
231e7792ce2SRob Clark # define TBG_CNTRL_0_SYNC_MTHD    (1 << 6)
232e7792ce2SRob Clark # define TBG_CNTRL_0_SYNC_ONCE    (1 << 7)
233e7792ce2SRob Clark #define REG_TBG_CNTRL_1           REG(0x00, 0xcb)     /* write */
234088d61d1SSebastian Hesselbarth # define TBG_CNTRL_1_H_TGL        (1 << 0)
235088d61d1SSebastian Hesselbarth # define TBG_CNTRL_1_V_TGL        (1 << 1)
236088d61d1SSebastian Hesselbarth # define TBG_CNTRL_1_TGL_EN       (1 << 2)
237088d61d1SSebastian Hesselbarth # define TBG_CNTRL_1_X_EXT        (1 << 3)
238088d61d1SSebastian Hesselbarth # define TBG_CNTRL_1_H_EXT        (1 << 4)
239088d61d1SSebastian Hesselbarth # define TBG_CNTRL_1_V_EXT        (1 << 5)
240e7792ce2SRob Clark # define TBG_CNTRL_1_DWIN_DIS     (1 << 6)
241e7792ce2SRob Clark #define REG_ENABLE_SPACE          REG(0x00, 0xd6)     /* write */
242e7792ce2SRob Clark #define REG_HVF_CNTRL_0           REG(0x00, 0xe4)     /* write */
243e7792ce2SRob Clark # define HVF_CNTRL_0_SM           (1 << 7)
244e7792ce2SRob Clark # define HVF_CNTRL_0_RWB          (1 << 6)
245e7792ce2SRob Clark # define HVF_CNTRL_0_PREFIL(x)    (((x) & 3) << 2)
246e7792ce2SRob Clark # define HVF_CNTRL_0_INTPOL(x)    (((x) & 3) << 0)
247e7792ce2SRob Clark #define REG_HVF_CNTRL_1           REG(0x00, 0xe5)     /* write */
248e7792ce2SRob Clark # define HVF_CNTRL_1_FOR          (1 << 0)
249e7792ce2SRob Clark # define HVF_CNTRL_1_YUVBLK       (1 << 1)
250e7792ce2SRob Clark # define HVF_CNTRL_1_VQR(x)       (((x) & 3) << 2)
251e7792ce2SRob Clark # define HVF_CNTRL_1_PAD(x)       (((x) & 3) << 4)
252e7792ce2SRob Clark # define HVF_CNTRL_1_SEMI_PLANAR  (1 << 6)
253e7792ce2SRob Clark #define REG_RPT_CNTRL             REG(0x00, 0xf0)     /* write */
2542807ba75SRussell King # define RPT_CNTRL_REPEAT(x)      ((x) & 15)
255c4c11dd1SRussell King #define REG_I2S_FORMAT            REG(0x00, 0xfc)     /* read/write */
256935b9ca3SRussell King # define I2S_FORMAT_PHILIPS       (0 << 0)
257935b9ca3SRussell King # define I2S_FORMAT_LEFT_J        (2 << 0)
258935b9ca3SRussell King # define I2S_FORMAT_RIGHT_J       (3 << 0)
259c4c11dd1SRussell King #define REG_AIP_CLKSEL            REG(0x00, 0xfd)     /* write */
26010df1a95SJean-Francois Moine # define AIP_CLKSEL_AIP_SPDIF	  (0 << 3)
26110df1a95SJean-Francois Moine # define AIP_CLKSEL_AIP_I2S	  (1 << 3)
26210df1a95SJean-Francois Moine # define AIP_CLKSEL_FS_ACLK	  (0 << 0)
26310df1a95SJean-Francois Moine # define AIP_CLKSEL_FS_MCLK	  (1 << 0)
26410df1a95SJean-Francois Moine # define AIP_CLKSEL_FS_FS64SPDIF  (2 << 0)
265e7792ce2SRob Clark 
266e7792ce2SRob Clark /* Page 02h: PLL settings */
267e7792ce2SRob Clark #define REG_PLL_SERIAL_1          REG(0x02, 0x00)     /* read/write */
268e7792ce2SRob Clark # define PLL_SERIAL_1_SRL_FDN     (1 << 0)
269e7792ce2SRob Clark # define PLL_SERIAL_1_SRL_IZ(x)   (((x) & 3) << 1)
270e7792ce2SRob Clark # define PLL_SERIAL_1_SRL_MAN_IZ  (1 << 6)
271e7792ce2SRob Clark #define REG_PLL_SERIAL_2          REG(0x02, 0x01)     /* read/write */
2723ae471f7SJean-Francois Moine # define PLL_SERIAL_2_SRL_NOSC(x) ((x) << 0)
273e7792ce2SRob Clark # define PLL_SERIAL_2_SRL_PR(x)   (((x) & 0xf) << 4)
274e7792ce2SRob Clark #define REG_PLL_SERIAL_3          REG(0x02, 0x02)     /* read/write */
275e7792ce2SRob Clark # define PLL_SERIAL_3_SRL_CCIR    (1 << 0)
276e7792ce2SRob Clark # define PLL_SERIAL_3_SRL_DE      (1 << 2)
277e7792ce2SRob Clark # define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4)
278e7792ce2SRob Clark #define REG_SERIALIZER            REG(0x02, 0x03)     /* read/write */
279e7792ce2SRob Clark #define REG_BUFFER_OUT            REG(0x02, 0x04)     /* read/write */
280e7792ce2SRob Clark #define REG_PLL_SCG1              REG(0x02, 0x05)     /* read/write */
281e7792ce2SRob Clark #define REG_PLL_SCG2              REG(0x02, 0x06)     /* read/write */
282e7792ce2SRob Clark #define REG_PLL_SCGN1             REG(0x02, 0x07)     /* read/write */
283e7792ce2SRob Clark #define REG_PLL_SCGN2             REG(0x02, 0x08)     /* read/write */
284e7792ce2SRob Clark #define REG_PLL_SCGR1             REG(0x02, 0x09)     /* read/write */
285e7792ce2SRob Clark #define REG_PLL_SCGR2             REG(0x02, 0x0a)     /* read/write */
286e7792ce2SRob Clark #define REG_AUDIO_DIV             REG(0x02, 0x0e)     /* read/write */
287c4c11dd1SRussell King # define AUDIO_DIV_SERCLK_1       0
288c4c11dd1SRussell King # define AUDIO_DIV_SERCLK_2       1
289c4c11dd1SRussell King # define AUDIO_DIV_SERCLK_4       2
290c4c11dd1SRussell King # define AUDIO_DIV_SERCLK_8       3
291c4c11dd1SRussell King # define AUDIO_DIV_SERCLK_16      4
292c4c11dd1SRussell King # define AUDIO_DIV_SERCLK_32      5
293e7792ce2SRob Clark #define REG_SEL_CLK               REG(0x02, 0x11)     /* read/write */
294e7792ce2SRob Clark # define SEL_CLK_SEL_CLK1         (1 << 0)
295e7792ce2SRob Clark # define SEL_CLK_SEL_VRF_CLK(x)   (((x) & 3) << 1)
296e7792ce2SRob Clark # define SEL_CLK_ENA_SC_CLK       (1 << 3)
297e7792ce2SRob Clark #define REG_ANA_GENERAL           REG(0x02, 0x12)     /* read/write */
298e7792ce2SRob Clark 
299e7792ce2SRob Clark 
300e7792ce2SRob Clark /* Page 09h: EDID Control */
301e7792ce2SRob Clark #define REG_EDID_DATA_0           REG(0x09, 0x00)     /* read */
302e7792ce2SRob Clark /* next 127 successive registers are the EDID block */
303e7792ce2SRob Clark #define REG_EDID_CTRL             REG(0x09, 0xfa)     /* read/write */
304e7792ce2SRob Clark #define REG_DDC_ADDR              REG(0x09, 0xfb)     /* read/write */
305e7792ce2SRob Clark #define REG_DDC_OFFS              REG(0x09, 0xfc)     /* read/write */
306e7792ce2SRob Clark #define REG_DDC_SEGM_ADDR         REG(0x09, 0xfd)     /* read/write */
307e7792ce2SRob Clark #define REG_DDC_SEGM              REG(0x09, 0xfe)     /* read/write */
308e7792ce2SRob Clark 
309e7792ce2SRob Clark 
310e7792ce2SRob Clark /* Page 10h: information frames and packets */
311c4c11dd1SRussell King #define REG_IF1_HB0               REG(0x10, 0x20)     /* read/write */
312c4c11dd1SRussell King #define REG_IF2_HB0               REG(0x10, 0x40)     /* read/write */
313c4c11dd1SRussell King #define REG_IF3_HB0               REG(0x10, 0x60)     /* read/write */
314c4c11dd1SRussell King #define REG_IF4_HB0               REG(0x10, 0x80)     /* read/write */
315c4c11dd1SRussell King #define REG_IF5_HB0               REG(0x10, 0xa0)     /* read/write */
316e7792ce2SRob Clark 
317e7792ce2SRob Clark 
318e7792ce2SRob Clark /* Page 11h: audio settings and content info packets */
319e7792ce2SRob Clark #define REG_AIP_CNTRL_0           REG(0x11, 0x00)     /* read/write */
320e7792ce2SRob Clark # define AIP_CNTRL_0_RST_FIFO     (1 << 0)
321e7792ce2SRob Clark # define AIP_CNTRL_0_SWAP         (1 << 1)
322e7792ce2SRob Clark # define AIP_CNTRL_0_LAYOUT       (1 << 2)
323e7792ce2SRob Clark # define AIP_CNTRL_0_ACR_MAN      (1 << 5)
324e7792ce2SRob Clark # define AIP_CNTRL_0_RST_CTS      (1 << 6)
325c4c11dd1SRussell King #define REG_CA_I2S                REG(0x11, 0x01)     /* read/write */
326c4c11dd1SRussell King # define CA_I2S_CA_I2S(x)         (((x) & 31) << 0)
327c4c11dd1SRussell King # define CA_I2S_HBR_CHSTAT        (1 << 6)
328c4c11dd1SRussell King #define REG_LATENCY_RD            REG(0x11, 0x04)     /* read/write */
329c4c11dd1SRussell King #define REG_ACR_CTS_0             REG(0x11, 0x05)     /* read/write */
330c4c11dd1SRussell King #define REG_ACR_CTS_1             REG(0x11, 0x06)     /* read/write */
331c4c11dd1SRussell King #define REG_ACR_CTS_2             REG(0x11, 0x07)     /* read/write */
332c4c11dd1SRussell King #define REG_ACR_N_0               REG(0x11, 0x08)     /* read/write */
333c4c11dd1SRussell King #define REG_ACR_N_1               REG(0x11, 0x09)     /* read/write */
334c4c11dd1SRussell King #define REG_ACR_N_2               REG(0x11, 0x0a)     /* read/write */
335c4c11dd1SRussell King #define REG_CTS_N                 REG(0x11, 0x0c)     /* read/write */
336c4c11dd1SRussell King # define CTS_N_K(x)               (((x) & 7) << 0)
337c4c11dd1SRussell King # define CTS_N_M(x)               (((x) & 3) << 4)
338e7792ce2SRob Clark #define REG_ENC_CNTRL             REG(0x11, 0x0d)     /* read/write */
339e7792ce2SRob Clark # define ENC_CNTRL_RST_ENC        (1 << 0)
340e7792ce2SRob Clark # define ENC_CNTRL_RST_SEL        (1 << 1)
341e7792ce2SRob Clark # define ENC_CNTRL_CTL_CODE(x)    (((x) & 3) << 2)
342c4c11dd1SRussell King #define REG_DIP_FLAGS             REG(0x11, 0x0e)     /* read/write */
343c4c11dd1SRussell King # define DIP_FLAGS_ACR            (1 << 0)
344c4c11dd1SRussell King # define DIP_FLAGS_GC             (1 << 1)
345c4c11dd1SRussell King #define REG_DIP_IF_FLAGS          REG(0x11, 0x0f)     /* read/write */
346c4c11dd1SRussell King # define DIP_IF_FLAGS_IF1         (1 << 1)
347c4c11dd1SRussell King # define DIP_IF_FLAGS_IF2         (1 << 2)
348c4c11dd1SRussell King # define DIP_IF_FLAGS_IF3         (1 << 3)
349c4c11dd1SRussell King # define DIP_IF_FLAGS_IF4         (1 << 4)
350c4c11dd1SRussell King # define DIP_IF_FLAGS_IF5         (1 << 5)
351c4c11dd1SRussell King #define REG_CH_STAT_B(x)          REG(0x11, 0x14 + (x)) /* read/write */
352e7792ce2SRob Clark 
353e7792ce2SRob Clark 
354e7792ce2SRob Clark /* Page 12h: HDCP and OTP */
355e7792ce2SRob Clark #define REG_TX3                   REG(0x12, 0x9a)     /* read/write */
356063b472fSRussell King #define REG_TX4                   REG(0x12, 0x9b)     /* read/write */
357063b472fSRussell King # define TX4_PD_RAM               (1 << 1)
358e7792ce2SRob Clark #define REG_TX33                  REG(0x12, 0xb8)     /* read/write */
359e7792ce2SRob Clark # define TX33_HDMI                (1 << 1)
360e7792ce2SRob Clark 
361e7792ce2SRob Clark 
362e7792ce2SRob Clark /* Page 13h: Gamut related metadata packets */
363e7792ce2SRob Clark 
364e7792ce2SRob Clark 
365e7792ce2SRob Clark 
366e7792ce2SRob Clark /* CEC registers: (not paged)
367e7792ce2SRob Clark  */
36812473b7dSJean-Francois Moine #define REG_CEC_INTSTATUS	  0xee		      /* read */
36912473b7dSJean-Francois Moine # define CEC_INTSTATUS_CEC	  (1 << 0)
37012473b7dSJean-Francois Moine # define CEC_INTSTATUS_HDMI	  (1 << 1)
3717e8675f0SRussell King #define REG_CEC_CAL_XOSC_CTRL1    0xf2
3727e8675f0SRussell King # define CEC_CAL_XOSC_CTRL1_ENA_CAL	BIT(0)
3737e8675f0SRussell King #define REG_CEC_DES_FREQ2         0xf5
3747e8675f0SRussell King # define CEC_DES_FREQ2_DIS_AUTOCAL BIT(7)
3757e8675f0SRussell King #define REG_CEC_CLK               0xf6
3767e8675f0SRussell King # define CEC_CLK_FRO              0x11
377e7792ce2SRob Clark #define REG_CEC_FRO_IM_CLK_CTRL   0xfb                /* read/write */
378e7792ce2SRob Clark # define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7)
379e7792ce2SRob Clark # define CEC_FRO_IM_CLK_CTRL_ENA_OTP   (1 << 6)
380e7792ce2SRob Clark # define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1)
381e7792ce2SRob Clark # define CEC_FRO_IM_CLK_CTRL_FRO_DIV   (1 << 0)
38212473b7dSJean-Francois Moine #define REG_CEC_RXSHPDINTENA	  0xfc		      /* read/write */
38312473b7dSJean-Francois Moine #define REG_CEC_RXSHPDINT	  0xfd		      /* read */
384ec5d3e83SRussell King # define CEC_RXSHPDINT_RXSENS     BIT(0)
385ec5d3e83SRussell King # define CEC_RXSHPDINT_HPD        BIT(1)
386e7792ce2SRob Clark #define REG_CEC_RXSHPDLEV         0xfe                /* read */
387e7792ce2SRob Clark # define CEC_RXSHPDLEV_RXSENS     (1 << 0)
388e7792ce2SRob Clark # define CEC_RXSHPDLEV_HPD        (1 << 1)
389e7792ce2SRob Clark 
390e7792ce2SRob Clark #define REG_CEC_ENAMODS           0xff                /* read/write */
3917e8675f0SRussell King # define CEC_ENAMODS_EN_CEC_CLK   (1 << 7)
392e7792ce2SRob Clark # define CEC_ENAMODS_DIS_FRO      (1 << 6)
393e7792ce2SRob Clark # define CEC_ENAMODS_DIS_CCLK     (1 << 5)
394e7792ce2SRob Clark # define CEC_ENAMODS_EN_RXSENS    (1 << 2)
395e7792ce2SRob Clark # define CEC_ENAMODS_EN_HDMI      (1 << 1)
396e7792ce2SRob Clark # define CEC_ENAMODS_EN_CEC       (1 << 0)
397e7792ce2SRob Clark 
398e7792ce2SRob Clark 
399e7792ce2SRob Clark /* Device versions: */
400e7792ce2SRob Clark #define TDA9989N2                 0x0101
401e7792ce2SRob Clark #define TDA19989                  0x0201
402e7792ce2SRob Clark #define TDA19989N2                0x0202
403e7792ce2SRob Clark #define TDA19988                  0x0301
404e7792ce2SRob Clark 
405e7792ce2SRob Clark static void
cec_write(struct tda998x_priv * priv,u16 addr,u8 val)406e66e03abSRussell King cec_write(struct tda998x_priv *priv, u16 addr, u8 val)
407e7792ce2SRob Clark {
408e66e03abSRussell King 	u8 buf[] = {addr, val};
40914e5b588SRussell King 	struct i2c_msg msg = {
41014e5b588SRussell King 		.addr = priv->cec_addr,
41114e5b588SRussell King 		.len = 2,
41214e5b588SRussell King 		.buf = buf,
41314e5b588SRussell King 	};
414e7792ce2SRob Clark 	int ret;
415e7792ce2SRob Clark 
41614e5b588SRussell King 	ret = i2c_transfer(priv->hdmi->adapter, &msg, 1);
417e7792ce2SRob Clark 	if (ret < 0)
41814e5b588SRussell King 		dev_err(&priv->hdmi->dev, "Error %d writing to cec:0x%x\n",
41914e5b588SRussell King 			ret, addr);
420e7792ce2SRob Clark }
421e7792ce2SRob Clark 
422e66e03abSRussell King static u8
cec_read(struct tda998x_priv * priv,u8 addr)423e66e03abSRussell King cec_read(struct tda998x_priv *priv, u8 addr)
424e7792ce2SRob Clark {
425e66e03abSRussell King 	u8 val;
42614e5b588SRussell King 	struct i2c_msg msg[2] = {
42714e5b588SRussell King 		{
42814e5b588SRussell King 			.addr = priv->cec_addr,
42914e5b588SRussell King 			.len = 1,
43014e5b588SRussell King 			.buf = &addr,
43114e5b588SRussell King 		}, {
43214e5b588SRussell King 			.addr = priv->cec_addr,
43314e5b588SRussell King 			.flags = I2C_M_RD,
43414e5b588SRussell King 			.len = 1,
43514e5b588SRussell King 			.buf = &val,
43614e5b588SRussell King 		},
43714e5b588SRussell King 	};
438e7792ce2SRob Clark 	int ret;
439e7792ce2SRob Clark 
44014e5b588SRussell King 	ret = i2c_transfer(priv->hdmi->adapter, msg, ARRAY_SIZE(msg));
44114e5b588SRussell King 	if (ret < 0) {
44214e5b588SRussell King 		dev_err(&priv->hdmi->dev, "Error %d reading from cec:0x%x\n",
44314e5b588SRussell King 			ret, addr);
44414e5b588SRussell King 		val = 0;
44514e5b588SRussell King 	}
446e7792ce2SRob Clark 
447e7792ce2SRob Clark 	return val;
448e7792ce2SRob Clark }
449e7792ce2SRob Clark 
cec_enamods(struct tda998x_priv * priv,u8 mods,bool enable)4507e8675f0SRussell King static void cec_enamods(struct tda998x_priv *priv, u8 mods, bool enable)
4517e8675f0SRussell King {
4527e8675f0SRussell King 	int val = cec_read(priv, REG_CEC_ENAMODS);
4537e8675f0SRussell King 
4547e8675f0SRussell King 	if (val < 0)
4557e8675f0SRussell King 		return;
4567e8675f0SRussell King 
4577e8675f0SRussell King 	if (enable)
4587e8675f0SRussell King 		val |= mods;
4597e8675f0SRussell King 	else
4607e8675f0SRussell King 		val &= ~mods;
4617e8675f0SRussell King 
4627e8675f0SRussell King 	cec_write(priv, REG_CEC_ENAMODS, val);
4637e8675f0SRussell King }
4647e8675f0SRussell King 
tda998x_cec_set_calibration(struct tda998x_priv * priv,bool enable)4657e8675f0SRussell King static void tda998x_cec_set_calibration(struct tda998x_priv *priv, bool enable)
4667e8675f0SRussell King {
4677e8675f0SRussell King 	if (enable) {
4687e8675f0SRussell King 		u8 val;
4697e8675f0SRussell King 
4707e8675f0SRussell King 		cec_write(priv, 0xf3, 0xc0);
4717e8675f0SRussell King 		cec_write(priv, 0xf4, 0xd4);
4727e8675f0SRussell King 
4737e8675f0SRussell King 		/* Enable automatic calibration mode */
4747e8675f0SRussell King 		val = cec_read(priv, REG_CEC_DES_FREQ2);
4757e8675f0SRussell King 		val &= ~CEC_DES_FREQ2_DIS_AUTOCAL;
4767e8675f0SRussell King 		cec_write(priv, REG_CEC_DES_FREQ2, val);
4777e8675f0SRussell King 
4787e8675f0SRussell King 		/* Enable free running oscillator */
4797e8675f0SRussell King 		cec_write(priv, REG_CEC_CLK, CEC_CLK_FRO);
4807e8675f0SRussell King 		cec_enamods(priv, CEC_ENAMODS_DIS_FRO, false);
4817e8675f0SRussell King 
4827e8675f0SRussell King 		cec_write(priv, REG_CEC_CAL_XOSC_CTRL1,
4837e8675f0SRussell King 			  CEC_CAL_XOSC_CTRL1_ENA_CAL);
4847e8675f0SRussell King 	} else {
4857e8675f0SRussell King 		cec_write(priv, REG_CEC_CAL_XOSC_CTRL1, 0);
4867e8675f0SRussell King 	}
4877e8675f0SRussell King }
4887e8675f0SRussell King 
4897e8675f0SRussell King /*
4907e8675f0SRussell King  * Calibration for the internal oscillator: we need to set calibration mode,
4917e8675f0SRussell King  * and then pulse the IRQ line low for a 10ms ± 1% period.
4927e8675f0SRussell King  */
tda998x_cec_calibration(struct tda998x_priv * priv)4937e8675f0SRussell King static void tda998x_cec_calibration(struct tda998x_priv *priv)
4947e8675f0SRussell King {
4957e8675f0SRussell King 	struct gpio_desc *calib = priv->calib;
4967e8675f0SRussell King 
4977e8675f0SRussell King 	mutex_lock(&priv->edid_mutex);
4987e8675f0SRussell King 	if (priv->hdmi->irq > 0)
4997e8675f0SRussell King 		disable_irq(priv->hdmi->irq);
5007e8675f0SRussell King 	gpiod_direction_output(calib, 1);
5017e8675f0SRussell King 	tda998x_cec_set_calibration(priv, true);
5027e8675f0SRussell King 
5037e8675f0SRussell King 	local_irq_disable();
5047e8675f0SRussell King 	gpiod_set_value(calib, 0);
5057e8675f0SRussell King 	mdelay(10);
5067e8675f0SRussell King 	gpiod_set_value(calib, 1);
5077e8675f0SRussell King 	local_irq_enable();
5087e8675f0SRussell King 
5097e8675f0SRussell King 	tda998x_cec_set_calibration(priv, false);
5107e8675f0SRussell King 	gpiod_direction_input(calib);
5117e8675f0SRussell King 	if (priv->hdmi->irq > 0)
5127e8675f0SRussell King 		enable_irq(priv->hdmi->irq);
5137e8675f0SRussell King 	mutex_unlock(&priv->edid_mutex);
5147e8675f0SRussell King }
5157e8675f0SRussell King 
tda998x_cec_hook_init(void * data)5167e8675f0SRussell King static int tda998x_cec_hook_init(void *data)
5177e8675f0SRussell King {
5187e8675f0SRussell King 	struct tda998x_priv *priv = data;
5197e8675f0SRussell King 	struct gpio_desc *calib;
5207e8675f0SRussell King 
5217e8675f0SRussell King 	calib = gpiod_get(&priv->hdmi->dev, "nxp,calib", GPIOD_ASIS);
5227e8675f0SRussell King 	if (IS_ERR(calib)) {
5237e8675f0SRussell King 		dev_warn(&priv->hdmi->dev, "failed to get calibration gpio: %ld\n",
5247e8675f0SRussell King 			 PTR_ERR(calib));
5257e8675f0SRussell King 		return PTR_ERR(calib);
5267e8675f0SRussell King 	}
5277e8675f0SRussell King 
5287e8675f0SRussell King 	priv->calib = calib;
5297e8675f0SRussell King 
5307e8675f0SRussell King 	return 0;
5317e8675f0SRussell King }
5327e8675f0SRussell King 
tda998x_cec_hook_exit(void * data)5337e8675f0SRussell King static void tda998x_cec_hook_exit(void *data)
5347e8675f0SRussell King {
5357e8675f0SRussell King 	struct tda998x_priv *priv = data;
5367e8675f0SRussell King 
5377e8675f0SRussell King 	gpiod_put(priv->calib);
5387e8675f0SRussell King 	priv->calib = NULL;
5397e8675f0SRussell King }
5407e8675f0SRussell King 
tda998x_cec_hook_open(void * data)5417e8675f0SRussell King static int tda998x_cec_hook_open(void *data)
5427e8675f0SRussell King {
5437e8675f0SRussell King 	struct tda998x_priv *priv = data;
5447e8675f0SRussell King 
5457e8675f0SRussell King 	cec_enamods(priv, CEC_ENAMODS_EN_CEC_CLK | CEC_ENAMODS_EN_CEC, true);
5467e8675f0SRussell King 	tda998x_cec_calibration(priv);
5477e8675f0SRussell King 
5487e8675f0SRussell King 	return 0;
5497e8675f0SRussell King }
5507e8675f0SRussell King 
tda998x_cec_hook_release(void * data)5517e8675f0SRussell King static void tda998x_cec_hook_release(void *data)
5527e8675f0SRussell King {
5537e8675f0SRussell King 	struct tda998x_priv *priv = data;
5547e8675f0SRussell King 
5557e8675f0SRussell King 	cec_enamods(priv, CEC_ENAMODS_EN_CEC_CLK | CEC_ENAMODS_EN_CEC, false);
5567e8675f0SRussell King }
5577e8675f0SRussell King 
5587d2eadc9SJean-Francois Moine static int
set_page(struct tda998x_priv * priv,u16 reg)559e66e03abSRussell King set_page(struct tda998x_priv *priv, u16 reg)
560e7792ce2SRob Clark {
561e7792ce2SRob Clark 	if (REG2PAGE(reg) != priv->current_page) {
5622f7f730aSJean-Francois Moine 		struct i2c_client *client = priv->hdmi;
563e66e03abSRussell King 		u8 buf[] = {
564e7792ce2SRob Clark 				REG_CURPAGE, REG2PAGE(reg)
565e7792ce2SRob Clark 		};
566e7792ce2SRob Clark 		int ret = i2c_master_send(client, buf, sizeof(buf));
5677d2eadc9SJean-Francois Moine 		if (ret < 0) {
568288ffc73SJulia Lawall 			dev_err(&client->dev, "%s %04x err %d\n", __func__,
569704d63f5SJean-Francois Moine 					reg, ret);
5707d2eadc9SJean-Francois Moine 			return ret;
5717d2eadc9SJean-Francois Moine 		}
572e7792ce2SRob Clark 
573e7792ce2SRob Clark 		priv->current_page = REG2PAGE(reg);
574e7792ce2SRob Clark 	}
5757d2eadc9SJean-Francois Moine 	return 0;
576e7792ce2SRob Clark }
577e7792ce2SRob Clark 
578e7792ce2SRob Clark static int
reg_read_range(struct tda998x_priv * priv,u16 reg,char * buf,int cnt)579e66e03abSRussell King reg_read_range(struct tda998x_priv *priv, u16 reg, char *buf, int cnt)
580e7792ce2SRob Clark {
5812f7f730aSJean-Francois Moine 	struct i2c_client *client = priv->hdmi;
582e66e03abSRussell King 	u8 addr = REG2ADDR(reg);
583e7792ce2SRob Clark 	int ret;
584e7792ce2SRob Clark 
585ed9a8426SJean-Francois Moine 	mutex_lock(&priv->mutex);
5867d2eadc9SJean-Francois Moine 	ret = set_page(priv, reg);
5877d2eadc9SJean-Francois Moine 	if (ret < 0)
588ed9a8426SJean-Francois Moine 		goto out;
589e7792ce2SRob Clark 
590e7792ce2SRob Clark 	ret = i2c_master_send(client, &addr, sizeof(addr));
591e7792ce2SRob Clark 	if (ret < 0)
592e7792ce2SRob Clark 		goto fail;
593e7792ce2SRob Clark 
594e7792ce2SRob Clark 	ret = i2c_master_recv(client, buf, cnt);
595e7792ce2SRob Clark 	if (ret < 0)
596e7792ce2SRob Clark 		goto fail;
597e7792ce2SRob Clark 
598ed9a8426SJean-Francois Moine 	goto out;
599e7792ce2SRob Clark 
600e7792ce2SRob Clark fail:
601e7792ce2SRob Clark 	dev_err(&client->dev, "Error %d reading from 0x%x\n", ret, reg);
602ed9a8426SJean-Francois Moine out:
603ed9a8426SJean-Francois Moine 	mutex_unlock(&priv->mutex);
604e7792ce2SRob Clark 	return ret;
605e7792ce2SRob Clark }
606e7792ce2SRob Clark 
607ca510eadSLaura Abbott #define MAX_WRITE_RANGE_BUF 32
608ca510eadSLaura Abbott 
609c4c11dd1SRussell King static void
reg_write_range(struct tda998x_priv * priv,u16 reg,u8 * p,int cnt)610e66e03abSRussell King reg_write_range(struct tda998x_priv *priv, u16 reg, u8 *p, int cnt)
611c4c11dd1SRussell King {
6122f7f730aSJean-Francois Moine 	struct i2c_client *client = priv->hdmi;
613ca510eadSLaura Abbott 	/* This is the maximum size of the buffer passed in */
614ca510eadSLaura Abbott 	u8 buf[MAX_WRITE_RANGE_BUF + 1];
615c4c11dd1SRussell King 	int ret;
616c4c11dd1SRussell King 
617ca510eadSLaura Abbott 	if (cnt > MAX_WRITE_RANGE_BUF) {
618ca510eadSLaura Abbott 		dev_err(&client->dev, "Fixed write buffer too small (%d)\n",
619ca510eadSLaura Abbott 				MAX_WRITE_RANGE_BUF);
620ca510eadSLaura Abbott 		return;
621ca510eadSLaura Abbott 	}
622ca510eadSLaura Abbott 
623c4c11dd1SRussell King 	buf[0] = REG2ADDR(reg);
624c4c11dd1SRussell King 	memcpy(&buf[1], p, cnt);
625c4c11dd1SRussell King 
626ed9a8426SJean-Francois Moine 	mutex_lock(&priv->mutex);
6277d2eadc9SJean-Francois Moine 	ret = set_page(priv, reg);
6287d2eadc9SJean-Francois Moine 	if (ret < 0)
629ed9a8426SJean-Francois Moine 		goto out;
630c4c11dd1SRussell King 
631c4c11dd1SRussell King 	ret = i2c_master_send(client, buf, cnt + 1);
632c4c11dd1SRussell King 	if (ret < 0)
633c4c11dd1SRussell King 		dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
634ed9a8426SJean-Francois Moine out:
635ed9a8426SJean-Francois Moine 	mutex_unlock(&priv->mutex);
636c4c11dd1SRussell King }
637c4c11dd1SRussell King 
6387d2eadc9SJean-Francois Moine static int
reg_read(struct tda998x_priv * priv,u16 reg)639e66e03abSRussell King reg_read(struct tda998x_priv *priv, u16 reg)
640e7792ce2SRob Clark {
641e66e03abSRussell King 	u8 val = 0;
6427d2eadc9SJean-Francois Moine 	int ret;
6437d2eadc9SJean-Francois Moine 
6447d2eadc9SJean-Francois Moine 	ret = reg_read_range(priv, reg, &val, sizeof(val));
6457d2eadc9SJean-Francois Moine 	if (ret < 0)
6467d2eadc9SJean-Francois Moine 		return ret;
647e7792ce2SRob Clark 	return val;
648e7792ce2SRob Clark }
649e7792ce2SRob Clark 
650e7792ce2SRob Clark static void
reg_write(struct tda998x_priv * priv,u16 reg,u8 val)651e66e03abSRussell King reg_write(struct tda998x_priv *priv, u16 reg, u8 val)
652e7792ce2SRob Clark {
6532f7f730aSJean-Francois Moine 	struct i2c_client *client = priv->hdmi;
654e66e03abSRussell King 	u8 buf[] = {REG2ADDR(reg), val};
655e7792ce2SRob Clark 	int ret;
656e7792ce2SRob Clark 
657ed9a8426SJean-Francois Moine 	mutex_lock(&priv->mutex);
6587d2eadc9SJean-Francois Moine 	ret = set_page(priv, reg);
6597d2eadc9SJean-Francois Moine 	if (ret < 0)
660ed9a8426SJean-Francois Moine 		goto out;
661e7792ce2SRob Clark 
662704d63f5SJean-Francois Moine 	ret = i2c_master_send(client, buf, sizeof(buf));
663e7792ce2SRob Clark 	if (ret < 0)
664e7792ce2SRob Clark 		dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
665ed9a8426SJean-Francois Moine out:
666ed9a8426SJean-Francois Moine 	mutex_unlock(&priv->mutex);
667e7792ce2SRob Clark }
668e7792ce2SRob Clark 
669e7792ce2SRob Clark static void
reg_write16(struct tda998x_priv * priv,u16 reg,u16 val)670e66e03abSRussell King reg_write16(struct tda998x_priv *priv, u16 reg, u16 val)
671e7792ce2SRob Clark {
6722f7f730aSJean-Francois Moine 	struct i2c_client *client = priv->hdmi;
673e66e03abSRussell King 	u8 buf[] = {REG2ADDR(reg), val >> 8, val};
674e7792ce2SRob Clark 	int ret;
675e7792ce2SRob Clark 
676ed9a8426SJean-Francois Moine 	mutex_lock(&priv->mutex);
6777d2eadc9SJean-Francois Moine 	ret = set_page(priv, reg);
6787d2eadc9SJean-Francois Moine 	if (ret < 0)
679ed9a8426SJean-Francois Moine 		goto out;
680e7792ce2SRob Clark 
681704d63f5SJean-Francois Moine 	ret = i2c_master_send(client, buf, sizeof(buf));
682e7792ce2SRob Clark 	if (ret < 0)
683e7792ce2SRob Clark 		dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
684ed9a8426SJean-Francois Moine out:
685ed9a8426SJean-Francois Moine 	mutex_unlock(&priv->mutex);
686e7792ce2SRob Clark }
687e7792ce2SRob Clark 
688e7792ce2SRob Clark static void
reg_set(struct tda998x_priv * priv,u16 reg,u8 val)689e66e03abSRussell King reg_set(struct tda998x_priv *priv, u16 reg, u8 val)
690e7792ce2SRob Clark {
6917d2eadc9SJean-Francois Moine 	int old_val;
6927d2eadc9SJean-Francois Moine 
6937d2eadc9SJean-Francois Moine 	old_val = reg_read(priv, reg);
6947d2eadc9SJean-Francois Moine 	if (old_val >= 0)
6957d2eadc9SJean-Francois Moine 		reg_write(priv, reg, old_val | val);
696e7792ce2SRob Clark }
697e7792ce2SRob Clark 
698e7792ce2SRob Clark static void
reg_clear(struct tda998x_priv * priv,u16 reg,u8 val)699e66e03abSRussell King reg_clear(struct tda998x_priv *priv, u16 reg, u8 val)
700e7792ce2SRob Clark {
7017d2eadc9SJean-Francois Moine 	int old_val;
7027d2eadc9SJean-Francois Moine 
7037d2eadc9SJean-Francois Moine 	old_val = reg_read(priv, reg);
7047d2eadc9SJean-Francois Moine 	if (old_val >= 0)
7057d2eadc9SJean-Francois Moine 		reg_write(priv, reg, old_val & ~val);
706e7792ce2SRob Clark }
707e7792ce2SRob Clark 
708e7792ce2SRob Clark static void
tda998x_reset(struct tda998x_priv * priv)7092f7f730aSJean-Francois Moine tda998x_reset(struct tda998x_priv *priv)
710e7792ce2SRob Clark {
711e7792ce2SRob Clark 	/* reset audio and i2c master: */
71281b53a16SJean-Francois Moine 	reg_write(priv, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
713e7792ce2SRob Clark 	msleep(50);
71481b53a16SJean-Francois Moine 	reg_write(priv, REG_SOFTRESET, 0);
715e7792ce2SRob Clark 	msleep(50);
716e7792ce2SRob Clark 
717e7792ce2SRob Clark 	/* reset transmitter: */
7182f7f730aSJean-Francois Moine 	reg_set(priv, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
7192f7f730aSJean-Francois Moine 	reg_clear(priv, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
720e7792ce2SRob Clark 
721e7792ce2SRob Clark 	/* PLL registers common configuration */
7222f7f730aSJean-Francois Moine 	reg_write(priv, REG_PLL_SERIAL_1, 0x00);
7232f7f730aSJean-Francois Moine 	reg_write(priv, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1));
7242f7f730aSJean-Francois Moine 	reg_write(priv, REG_PLL_SERIAL_3, 0x00);
7252f7f730aSJean-Francois Moine 	reg_write(priv, REG_SERIALIZER,   0x00);
7262f7f730aSJean-Francois Moine 	reg_write(priv, REG_BUFFER_OUT,   0x00);
7272f7f730aSJean-Francois Moine 	reg_write(priv, REG_PLL_SCG1,     0x00);
7282f7f730aSJean-Francois Moine 	reg_write(priv, REG_AUDIO_DIV,    AUDIO_DIV_SERCLK_8);
7292f7f730aSJean-Francois Moine 	reg_write(priv, REG_SEL_CLK,      SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
7302f7f730aSJean-Francois Moine 	reg_write(priv, REG_PLL_SCGN1,    0xfa);
7312f7f730aSJean-Francois Moine 	reg_write(priv, REG_PLL_SCGN2,    0x00);
7322f7f730aSJean-Francois Moine 	reg_write(priv, REG_PLL_SCGR1,    0x5b);
7332f7f730aSJean-Francois Moine 	reg_write(priv, REG_PLL_SCGR2,    0x00);
7342f7f730aSJean-Francois Moine 	reg_write(priv, REG_PLL_SCG2,     0x10);
735bcb2481dSRussell King 
736bcb2481dSRussell King 	/* Write the default value MUX register */
7372f7f730aSJean-Francois Moine 	reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24);
738e7792ce2SRob Clark }
739e7792ce2SRob Clark 
7400fc6f44dSRussell King /*
7410fc6f44dSRussell King  * The TDA998x has a problem when trying to read the EDID close to a
7420fc6f44dSRussell King  * HPD assertion: it needs a delay of 100ms to avoid timing out while
7430fc6f44dSRussell King  * trying to read EDID data.
7440fc6f44dSRussell King  *
74595a9b686SRussell King  * However, tda998x_connector_get_modes() may be called at any moment
7469525c4ddSRussell King  * after tda998x_connector_detect() indicates that we are connected, so
74795a9b686SRussell King  * we need to delay probing modes in tda998x_connector_get_modes() after
7480fc6f44dSRussell King  * we have seen a HPD inactive->active transition.  This code implements
7490fc6f44dSRussell King  * that delay.
7500fc6f44dSRussell King  */
tda998x_edid_delay_done(struct timer_list * t)751e99e88a9SKees Cook static void tda998x_edid_delay_done(struct timer_list *t)
7526833d26eSJean-Francois Moine {
753e99e88a9SKees Cook 	struct tda998x_priv *priv = from_timer(priv, t, edid_delay_timer);
7546833d26eSJean-Francois Moine 
7550fc6f44dSRussell King 	priv->edid_delay_active = false;
7560fc6f44dSRussell King 	wake_up(&priv->edid_delay_waitq);
7570fc6f44dSRussell King 	schedule_work(&priv->detect_work);
7580fc6f44dSRussell King }
7590fc6f44dSRussell King 
tda998x_edid_delay_start(struct tda998x_priv * priv)7600fc6f44dSRussell King static void tda998x_edid_delay_start(struct tda998x_priv *priv)
7610fc6f44dSRussell King {
7620fc6f44dSRussell King 	priv->edid_delay_active = true;
7630fc6f44dSRussell King 	mod_timer(&priv->edid_delay_timer, jiffies + HZ/10);
7640fc6f44dSRussell King }
7650fc6f44dSRussell King 
tda998x_edid_delay_wait(struct tda998x_priv * priv)7660fc6f44dSRussell King static int tda998x_edid_delay_wait(struct tda998x_priv *priv)
7670fc6f44dSRussell King {
7680fc6f44dSRussell King 	return wait_event_killable(priv->edid_delay_waitq, !priv->edid_delay_active);
7690fc6f44dSRussell King }
7700fc6f44dSRussell King 
7710fc6f44dSRussell King /*
7720fc6f44dSRussell King  * We need to run the KMS hotplug event helper outside of our threaded
7730fc6f44dSRussell King  * interrupt routine as this can call back into our get_modes method,
7740fc6f44dSRussell King  * which will want to make use of interrupts.
7750fc6f44dSRussell King  */
tda998x_detect_work(struct work_struct * work)7760fc6f44dSRussell King static void tda998x_detect_work(struct work_struct *work)
7770fc6f44dSRussell King {
7780fc6f44dSRussell King 	struct tda998x_priv *priv =
7790fc6f44dSRussell King 		container_of(work, struct tda998x_priv, detect_work);
780b1eb4f84SPeter Rosin 	struct drm_device *dev = priv->connector.dev;
7810fc6f44dSRussell King 
7820fc6f44dSRussell King 	if (dev)
7830fc6f44dSRussell King 		drm_kms_helper_hotplug_event(dev);
7846833d26eSJean-Francois Moine }
7856833d26eSJean-Francois Moine 
78612473b7dSJean-Francois Moine /*
78712473b7dSJean-Francois Moine  * only 2 interrupts may occur: screen plug/unplug and EDID read
78812473b7dSJean-Francois Moine  */
tda998x_irq_thread(int irq,void * data)78912473b7dSJean-Francois Moine static irqreturn_t tda998x_irq_thread(int irq, void *data)
79012473b7dSJean-Francois Moine {
79112473b7dSJean-Francois Moine 	struct tda998x_priv *priv = data;
79212473b7dSJean-Francois Moine 	u8 sta, cec, lvl, flag0, flag1, flag2;
793f84a97d4SRussell King 	bool handled = false;
79412473b7dSJean-Francois Moine 
79512473b7dSJean-Francois Moine 	sta = cec_read(priv, REG_CEC_INTSTATUS);
796ae81553cSRussell King 	if (sta & CEC_INTSTATUS_HDMI) {
79712473b7dSJean-Francois Moine 		cec = cec_read(priv, REG_CEC_RXSHPDINT);
79812473b7dSJean-Francois Moine 		lvl = cec_read(priv, REG_CEC_RXSHPDLEV);
79912473b7dSJean-Francois Moine 		flag0 = reg_read(priv, REG_INT_FLAGS_0);
80012473b7dSJean-Francois Moine 		flag1 = reg_read(priv, REG_INT_FLAGS_1);
80112473b7dSJean-Francois Moine 		flag2 = reg_read(priv, REG_INT_FLAGS_2);
80212473b7dSJean-Francois Moine 		DRM_DEBUG_DRIVER(
80312473b7dSJean-Francois Moine 			"tda irq sta %02x cec %02x lvl %02x f0 %02x f1 %02x f2 %02x\n",
80412473b7dSJean-Francois Moine 			sta, cec, lvl, flag0, flag1, flag2);
805ec5d3e83SRussell King 
806ec5d3e83SRussell King 		if (cec & CEC_RXSHPDINT_HPD) {
8077e8675f0SRussell King 			if (lvl & CEC_RXSHPDLEV_HPD) {
8080fc6f44dSRussell King 				tda998x_edid_delay_start(priv);
8097e8675f0SRussell King 			} else {
8100fc6f44dSRussell King 				schedule_work(&priv->detect_work);
811ece485d5SDariusz Marcinkiewicz 				cec_notifier_phys_addr_invalidate(
812ece485d5SDariusz Marcinkiewicz 						priv->cec_notify);
8137e8675f0SRussell King 			}
8140fc6f44dSRussell King 
815f84a97d4SRussell King 			handled = true;
81612473b7dSJean-Francois Moine 		}
817ec5d3e83SRussell King 
818ec5d3e83SRussell King 		if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) {
819ec5d3e83SRussell King 			priv->wq_edid_wait = 0;
820ec5d3e83SRussell King 			wake_up(&priv->wq_edid);
821ec5d3e83SRussell King 			handled = true;
822ec5d3e83SRussell King 		}
823ae81553cSRussell King 	}
824ec5d3e83SRussell King 
825f84a97d4SRussell King 	return IRQ_RETVAL(handled);
82612473b7dSJean-Francois Moine }
82712473b7dSJean-Francois Moine 
828c4c11dd1SRussell King static void
tda998x_write_if(struct tda998x_priv * priv,u8 bit,u16 addr,union hdmi_infoframe * frame)829e66e03abSRussell King tda998x_write_if(struct tda998x_priv *priv, u8 bit, u16 addr,
83096795df1SRussell King 		 union hdmi_infoframe *frame)
831c4c11dd1SRussell King {
832ca510eadSLaura Abbott 	u8 buf[MAX_WRITE_RANGE_BUF];
83396795df1SRussell King 	ssize_t len;
83496795df1SRussell King 
83596795df1SRussell King 	len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
83696795df1SRussell King 	if (len < 0) {
83796795df1SRussell King 		dev_err(&priv->hdmi->dev,
83896795df1SRussell King 			"hdmi_infoframe_pack() type=0x%02x failed: %zd\n",
83996795df1SRussell King 			frame->any.type, len);
84096795df1SRussell King 		return;
84196795df1SRussell King 	}
84296795df1SRussell King 
8432f7f730aSJean-Francois Moine 	reg_clear(priv, REG_DIP_IF_FLAGS, bit);
84496795df1SRussell King 	reg_write_range(priv, addr, buf, len);
8452f7f730aSJean-Francois Moine 	reg_set(priv, REG_DIP_IF_FLAGS, bit);
846c4c11dd1SRussell King }
847c4c11dd1SRussell King 
tda998x_write_aif(struct tda998x_priv * priv,const struct hdmi_audio_infoframe * cea)848900b2b72SRussell King static void tda998x_write_aif(struct tda998x_priv *priv,
8492e9943aaSRussell King 			      const struct hdmi_audio_infoframe *cea)
850c4c11dd1SRussell King {
85196795df1SRussell King 	union hdmi_infoframe frame;
852c4c11dd1SRussell King 
85395db3b25SJyri Sarha 	frame.audio = *cea;
85496795df1SRussell King 
85596795df1SRussell King 	tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, &frame);
856c4c11dd1SRussell King }
857c4c11dd1SRussell King 
858c4c11dd1SRussell King static void
tda998x_write_avi(struct tda998x_priv * priv,const struct drm_display_mode * mode)85963f8f3baSLaurent Pinchart tda998x_write_avi(struct tda998x_priv *priv, const struct drm_display_mode *mode)
860c4c11dd1SRussell King {
86196795df1SRussell King 	union hdmi_infoframe frame;
862c4c11dd1SRussell King 
86313d0add3SVille Syrjälä 	drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
86413d0add3SVille Syrjälä 						 &priv->connector, mode);
86596795df1SRussell King 	frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
866fcc22c5fSRussell King 	drm_hdmi_avi_infoframe_quant_range(&frame.avi, &priv->connector, mode,
867fcc22c5fSRussell King 					   priv->rgb_quant_range);
868c4c11dd1SRussell King 
86996795df1SRussell King 	tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
870c4c11dd1SRussell King }
871c4c11dd1SRussell King 
tda998x_write_vsi(struct tda998x_priv * priv,const struct drm_display_mode * mode)87245a19dd3SRussell King static void tda998x_write_vsi(struct tda998x_priv *priv,
87345a19dd3SRussell King 			      const struct drm_display_mode *mode)
87445a19dd3SRussell King {
87545a19dd3SRussell King 	union hdmi_infoframe frame;
87645a19dd3SRussell King 
87745a19dd3SRussell King 	if (drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
87845a19dd3SRussell King 							&priv->connector,
87945a19dd3SRussell King 							mode))
88045a19dd3SRussell King 		reg_clear(priv, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF1);
88145a19dd3SRussell King 	else
88245a19dd3SRussell King 		tda998x_write_if(priv, DIP_IF_FLAGS_IF1, REG_IF1_HB0, &frame);
88345a19dd3SRussell King }
88445a19dd3SRussell King 
885ad975f93SRussell King /* Audio support */
886ad975f93SRussell King 
88726f7bf12SRussell King static const struct tda998x_audio_route tda998x_audio_route[AUDIO_ROUTE_NUM] = {
88826f7bf12SRussell King 	[AUDIO_ROUTE_I2S] = {
88926f7bf12SRussell King 		.ena_aclk = 1,
89026f7bf12SRussell King 		.mux_ap = MUX_AP_SELECT_I2S,
89126f7bf12SRussell King 		.aip_clksel = AIP_CLKSEL_AIP_I2S | AIP_CLKSEL_FS_ACLK,
89226f7bf12SRussell King 	},
89326f7bf12SRussell King 	[AUDIO_ROUTE_SPDIF] = {
89426f7bf12SRussell King 		.ena_aclk = 0,
89526f7bf12SRussell King 		.mux_ap = MUX_AP_SELECT_SPDIF,
89626f7bf12SRussell King 		.aip_clksel = AIP_CLKSEL_AIP_SPDIF | AIP_CLKSEL_FS_FS64SPDIF,
89726f7bf12SRussell King 	},
89826f7bf12SRussell King };
89926f7bf12SRussell King 
90026f7bf12SRussell King /* Configure the TDA998x audio data and clock routing. */
tda998x_derive_routing(struct tda998x_priv * priv,struct tda998x_audio_settings * s,unsigned int route)90126f7bf12SRussell King static int tda998x_derive_routing(struct tda998x_priv *priv,
90226f7bf12SRussell King 				  struct tda998x_audio_settings *s,
90326f7bf12SRussell King 				  unsigned int route)
90426f7bf12SRussell King {
90526f7bf12SRussell King 	s->route = &tda998x_audio_route[route];
90626f7bf12SRussell King 	s->ena_ap = priv->audio_port_enable[route];
90726f7bf12SRussell King 	if (s->ena_ap == 0) {
90826f7bf12SRussell King 		dev_err(&priv->hdmi->dev, "no audio configuration found\n");
90926f7bf12SRussell King 		return -EINVAL;
91026f7bf12SRussell King 	}
91126f7bf12SRussell King 
91226f7bf12SRussell King 	return 0;
91326f7bf12SRussell King }
91426f7bf12SRussell King 
9157dad3740SRussell King /*
9167dad3740SRussell King  * The audio clock divisor register controls a divider producing Audio_Clk_Out
9177dad3740SRussell King  * from SERclk by dividing it by 2^n where 0 <= n <= 5.  We don't know what
9187dad3740SRussell King  * Audio_Clk_Out or SERclk are. We guess SERclk is the same as TMDS clock.
9197dad3740SRussell King  *
9207dad3740SRussell King  * It seems that Audio_Clk_Out must be the smallest value that is greater
9217dad3740SRussell King  * than 128*fs, otherwise audio does not function. There is some suggestion
9227dad3740SRussell King  * that 126*fs is a better value.
9237dad3740SRussell King  */
tda998x_get_adiv(struct tda998x_priv * priv,unsigned int fs)9247dad3740SRussell King static u8 tda998x_get_adiv(struct tda998x_priv *priv, unsigned int fs)
9257dad3740SRussell King {
9267dad3740SRussell King 	unsigned long min_audio_clk = fs * 128;
9277dad3740SRussell King 	unsigned long ser_clk = priv->tmds_clock * 1000;
9287dad3740SRussell King 	u8 adiv;
9297dad3740SRussell King 
9307dad3740SRussell King 	for (adiv = AUDIO_DIV_SERCLK_32; adiv != AUDIO_DIV_SERCLK_1; adiv--)
9317dad3740SRussell King 		if (ser_clk > min_audio_clk << adiv)
9327dad3740SRussell King 			break;
9337dad3740SRussell King 
9347dad3740SRussell King 	dev_dbg(&priv->hdmi->dev,
9357dad3740SRussell King 		"ser_clk=%luHz fs=%uHz min_aclk=%luHz adiv=%d\n",
9367dad3740SRussell King 		ser_clk, fs, min_audio_clk, adiv);
9377dad3740SRussell King 
9387dad3740SRussell King 	return adiv;
9397dad3740SRussell King }
9407dad3740SRussell King 
941a03a915bSRussell King /*
942a03a915bSRussell King  * In auto-CTS mode, the TDA998x uses a "measured time stamp" counter to
943a03a915bSRussell King  * generate the CTS value.  It appears that the "measured time stamp" is
944a03a915bSRussell King  * the number of TDMS clock cycles within a number of audio input clock
945a03a915bSRussell King  * cycles defined by the k and N parameters defined below, in a similar
946a03a915bSRussell King  * way to that which is set out in the CTS generation in the HDMI spec.
947a03a915bSRussell King  *
948a03a915bSRussell King  *  tmdsclk ----> mts -> /m ---> CTS
949a03a915bSRussell King  *                 ^
950a03a915bSRussell King  *  sclk -> /k -> /N
951a03a915bSRussell King  *
952a03a915bSRussell King  * CTS = mts / m, where m is 2^M.
953a03a915bSRussell King  * /k is a divider based on the K value below, K+1 for K < 4, or 8 for K >= 4
954a03a915bSRussell King  * /N is a divider based on the HDMI specified N value.
955a03a915bSRussell King  *
956a03a915bSRussell King  * This produces the following equation:
957a03a915bSRussell King  *  CTS = tmds_clock * k * N / (sclk * m)
958a03a915bSRussell King  *
959a03a915bSRussell King  * When combined with the sink-side equation, and realising that sclk is
960a03a915bSRussell King  * bclk_ratio * fs, we end up with:
961a03a915bSRussell King  *  k = m * bclk_ratio / 128.
962a03a915bSRussell King  *
963a03a915bSRussell King  * Note: S/PDIF always uses a bclk_ratio of 64.
964a03a915bSRussell King  */
tda998x_derive_cts_n(struct tda998x_priv * priv,struct tda998x_audio_settings * settings,unsigned int ratio)965a03a915bSRussell King static int tda998x_derive_cts_n(struct tda998x_priv *priv,
966a03a915bSRussell King 				struct tda998x_audio_settings *settings,
967a03a915bSRussell King 				unsigned int ratio)
968a03a915bSRussell King {
969a03a915bSRussell King 	switch (ratio) {
970a03a915bSRussell King 	case 16:
971a03a915bSRussell King 		settings->cts_n = CTS_N_M(3) | CTS_N_K(0);
972a03a915bSRussell King 		break;
973a03a915bSRussell King 	case 32:
974a03a915bSRussell King 		settings->cts_n = CTS_N_M(3) | CTS_N_K(1);
975a03a915bSRussell King 		break;
976a03a915bSRussell King 	case 48:
977a03a915bSRussell King 		settings->cts_n = CTS_N_M(3) | CTS_N_K(2);
978a03a915bSRussell King 		break;
979a03a915bSRussell King 	case 64:
980a03a915bSRussell King 		settings->cts_n = CTS_N_M(3) | CTS_N_K(3);
981a03a915bSRussell King 		break;
982a03a915bSRussell King 	case 128:
983a03a915bSRussell King 		settings->cts_n = CTS_N_M(0) | CTS_N_K(0);
984a03a915bSRussell King 		break;
985a03a915bSRussell King 	default:
986a03a915bSRussell King 		dev_err(&priv->hdmi->dev, "unsupported bclk ratio %ufs\n",
987a03a915bSRussell King 			ratio);
988a03a915bSRussell King 		return -EINVAL;
989a03a915bSRussell King 	}
990a03a915bSRussell King 	return 0;
991a03a915bSRussell King }
992a03a915bSRussell King 
tda998x_audio_mute(struct tda998x_priv * priv,bool on)9932f7f730aSJean-Francois Moine static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
994c4c11dd1SRussell King {
995c4c11dd1SRussell King 	if (on) {
9962f7f730aSJean-Francois Moine 		reg_set(priv, REG_SOFTRESET, SOFTRESET_AUDIO);
9972f7f730aSJean-Francois Moine 		reg_clear(priv, REG_SOFTRESET, SOFTRESET_AUDIO);
9982f7f730aSJean-Francois Moine 		reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
999c4c11dd1SRussell King 	} else {
10002f7f730aSJean-Francois Moine 		reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
1001c4c11dd1SRussell King 	}
1002c4c11dd1SRussell King }
1003c4c11dd1SRussell King 
tda998x_configure_audio(struct tda998x_priv * priv)1004900b2b72SRussell King static void tda998x_configure_audio(struct tda998x_priv *priv)
1005c4c11dd1SRussell King {
1006900b2b72SRussell King 	const struct tda998x_audio_settings *settings = &priv->audio;
100726f7bf12SRussell King 	u8 buf[6], adiv;
1008e66e03abSRussell King 	u32 n;
1009c4c11dd1SRussell King 
101082642ab7SRussell King 	/* If audio is not configured, there is nothing to do. */
101182642ab7SRussell King 	if (settings->ena_ap == 0)
1012900b2b72SRussell King 		return;
101382642ab7SRussell King 
1014125a4f93SRussell King 	adiv = tda998x_get_adiv(priv, settings->sample_rate);
10157dad3740SRussell King 
1016c4c11dd1SRussell King 	/* Enable audio ports */
101782642ab7SRussell King 	reg_write(priv, REG_ENA_AP, settings->ena_ap);
101826f7bf12SRussell King 	reg_write(priv, REG_ENA_ACLK, settings->route->ena_aclk);
101926f7bf12SRussell King 	reg_write(priv, REG_MUX_AP, settings->route->mux_ap);
1020935b9ca3SRussell King 	reg_write(priv, REG_I2S_FORMAT, settings->i2s_format);
102126f7bf12SRussell King 	reg_write(priv, REG_AIP_CLKSEL, settings->route->aip_clksel);
1022a8b517e5SJean-Francois Moine 	reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT |
1023a8b517e5SJean-Francois Moine 					AIP_CNTRL_0_ACR_MAN);	/* auto CTS */
1024a03a915bSRussell King 	reg_write(priv, REG_CTS_N, settings->cts_n);
10252f7f730aSJean-Francois Moine 	reg_write(priv, REG_AUDIO_DIV, adiv);
1026c4c11dd1SRussell King 
1027c4c11dd1SRussell King 	/*
1028c4c11dd1SRussell King 	 * This is the approximate value of N, which happens to be
1029c4c11dd1SRussell King 	 * the recommended values for non-coherent clocks.
1030c4c11dd1SRussell King 	 */
1031125a4f93SRussell King 	n = 128 * settings->sample_rate / 1000;
1032c4c11dd1SRussell King 
1033c4c11dd1SRussell King 	/* Write the CTS and N values */
1034c4c11dd1SRussell King 	buf[0] = 0x44;
1035c4c11dd1SRussell King 	buf[1] = 0x42;
1036c4c11dd1SRussell King 	buf[2] = 0x01;
1037c4c11dd1SRussell King 	buf[3] = n;
1038c4c11dd1SRussell King 	buf[4] = n >> 8;
1039c4c11dd1SRussell King 	buf[5] = n >> 16;
10402f7f730aSJean-Francois Moine 	reg_write_range(priv, REG_ACR_CTS_0, buf, 6);
1041c4c11dd1SRussell King 
1042c4c11dd1SRussell King 	/* Reset CTS generator */
10432f7f730aSJean-Francois Moine 	reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
10442f7f730aSJean-Francois Moine 	reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
1045c4c11dd1SRussell King 
104695db3b25SJyri Sarha 	/* Write the channel status
104795db3b25SJyri Sarha 	 * The REG_CH_STAT_B-registers skip IEC958 AES2 byte, because
104895db3b25SJyri Sarha 	 * there is a separate register for each I2S wire.
104995db3b25SJyri Sarha 	 */
1050125a4f93SRussell King 	buf[0] = settings->status[0];
1051125a4f93SRussell King 	buf[1] = settings->status[1];
1052125a4f93SRussell King 	buf[2] = settings->status[3];
1053125a4f93SRussell King 	buf[3] = settings->status[4];
10542f7f730aSJean-Francois Moine 	reg_write_range(priv, REG_CH_STAT_B(0), buf, 4);
1055c4c11dd1SRussell King 
10562f7f730aSJean-Francois Moine 	tda998x_audio_mute(priv, true);
105773d5e253SJean-Francois Moine 	msleep(20);
10582f7f730aSJean-Francois Moine 	tda998x_audio_mute(priv, false);
1059c4c11dd1SRussell King 
1060125a4f93SRussell King 	tda998x_write_aif(priv, &settings->cea);
1061c4c11dd1SRussell King }
1062c4c11dd1SRussell King 
tda998x_audio_hw_params(struct device * dev,void * data,struct hdmi_codec_daifmt * daifmt,struct hdmi_codec_params * params)1063ad975f93SRussell King static int tda998x_audio_hw_params(struct device *dev, void *data,
1064ad975f93SRussell King 				   struct hdmi_codec_daifmt *daifmt,
1065ad975f93SRussell King 				   struct hdmi_codec_params *params)
1066ad975f93SRussell King {
1067ad975f93SRussell King 	struct tda998x_priv *priv = dev_get_drvdata(dev);
1068a03a915bSRussell King 	unsigned int bclk_ratio;
1069935b9ca3SRussell King 	bool spdif = daifmt->fmt == HDMI_SPDIF;
107071689160SRussell King 	int ret;
10712e9943aaSRussell King 	struct tda998x_audio_settings audio = {
1072ad975f93SRussell King 		.sample_rate = params->sample_rate,
1073ad975f93SRussell King 		.cea = params->cea,
1074ad975f93SRussell King 	};
1075ad975f93SRussell King 
1076ad975f93SRussell King 	memcpy(audio.status, params->iec.status,
1077ad975f93SRussell King 	       min(sizeof(audio.status), sizeof(params->iec.status)));
1078ad975f93SRussell King 
1079ad975f93SRussell King 	switch (daifmt->fmt) {
1080ad975f93SRussell King 	case HDMI_I2S:
1081935b9ca3SRussell King 		audio.i2s_format = I2S_FORMAT_PHILIPS;
1082935b9ca3SRussell King 		break;
1083935b9ca3SRussell King 	case HDMI_LEFT_J:
1084935b9ca3SRussell King 		audio.i2s_format = I2S_FORMAT_LEFT_J;
1085935b9ca3SRussell King 		break;
1086935b9ca3SRussell King 	case HDMI_RIGHT_J:
1087935b9ca3SRussell King 		audio.i2s_format = I2S_FORMAT_RIGHT_J;
1088ad975f93SRussell King 		break;
1089ad975f93SRussell King 	case HDMI_SPDIF:
1090935b9ca3SRussell King 		audio.i2s_format = 0;
1091ad975f93SRussell King 		break;
1092ad975f93SRussell King 	default:
1093ad975f93SRussell King 		dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt);
1094ad975f93SRussell King 		return -EINVAL;
1095ad975f93SRussell King 	}
1096ad975f93SRussell King 
1097935b9ca3SRussell King 	if (!spdif &&
1098935b9ca3SRussell King 	    (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
10999f1c8677SMark Brown 	     daifmt->bit_clk_provider || daifmt->frame_clk_provider)) {
1100935b9ca3SRussell King 		dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
1101935b9ca3SRussell King 			daifmt->bit_clk_inv, daifmt->frame_clk_inv,
11029f1c8677SMark Brown 			daifmt->bit_clk_provider,
11039f1c8677SMark Brown 			daifmt->frame_clk_provider);
1104ad975f93SRussell King 		return -EINVAL;
1105ad975f93SRussell King 	}
1106ad975f93SRussell King 
110726f7bf12SRussell King 	ret = tda998x_derive_routing(priv, &audio, AUDIO_ROUTE_I2S + spdif);
110826f7bf12SRussell King 	if (ret < 0)
110926f7bf12SRussell King 		return ret;
1110ad975f93SRussell King 
1111a03a915bSRussell King 	bclk_ratio = spdif ? 64 : params->sample_width * 2;
1112a03a915bSRussell King 	ret = tda998x_derive_cts_n(priv, &audio, bclk_ratio);
1113a03a915bSRussell King 	if (ret < 0)
1114a03a915bSRussell King 		return ret;
1115a03a915bSRussell King 
1116ad975f93SRussell King 	mutex_lock(&priv->audio_mutex);
11172e9943aaSRussell King 	priv->audio = audio;
1118900b2b72SRussell King 	if (priv->supports_infoframes && priv->sink_has_audio)
1119900b2b72SRussell King 		tda998x_configure_audio(priv);
1120ad975f93SRussell King 	mutex_unlock(&priv->audio_mutex);
1121ad975f93SRussell King 
1122900b2b72SRussell King 	return 0;
1123ad975f93SRussell King }
1124ad975f93SRussell King 
tda998x_audio_shutdown(struct device * dev,void * data)1125ad975f93SRussell King static void tda998x_audio_shutdown(struct device *dev, void *data)
1126ad975f93SRussell King {
1127ad975f93SRussell King 	struct tda998x_priv *priv = dev_get_drvdata(dev);
1128ad975f93SRussell King 
1129ad975f93SRussell King 	mutex_lock(&priv->audio_mutex);
1130ad975f93SRussell King 
1131ad975f93SRussell King 	reg_write(priv, REG_ENA_AP, 0);
113282642ab7SRussell King 	priv->audio.ena_ap = 0;
1133ad975f93SRussell King 
1134ad975f93SRussell King 	mutex_unlock(&priv->audio_mutex);
1135ad975f93SRussell King }
1136ad975f93SRussell King 
tda998x_audio_mute_stream(struct device * dev,void * data,bool enable,int direction)1137d789710fSKuninori Morimoto static int tda998x_audio_mute_stream(struct device *dev, void *data,
1138d789710fSKuninori Morimoto 				     bool enable, int direction)
1139ad975f93SRussell King {
1140ad975f93SRussell King 	struct tda998x_priv *priv = dev_get_drvdata(dev);
1141ad975f93SRussell King 
1142ad975f93SRussell King 	mutex_lock(&priv->audio_mutex);
1143ad975f93SRussell King 
1144ad975f93SRussell King 	tda998x_audio_mute(priv, enable);
1145ad975f93SRussell King 
1146ad975f93SRussell King 	mutex_unlock(&priv->audio_mutex);
1147ad975f93SRussell King 	return 0;
1148ad975f93SRussell King }
1149ad975f93SRussell King 
tda998x_audio_get_eld(struct device * dev,void * data,uint8_t * buf,size_t len)1150ad975f93SRussell King static int tda998x_audio_get_eld(struct device *dev, void *data,
1151ad975f93SRussell King 				 uint8_t *buf, size_t len)
1152ad975f93SRussell King {
1153ad975f93SRussell King 	struct tda998x_priv *priv = dev_get_drvdata(dev);
1154ad975f93SRussell King 
115502efac0fSRussell King 	mutex_lock(&priv->audio_mutex);
115602efac0fSRussell King 	memcpy(buf, priv->connector.eld,
115702efac0fSRussell King 	       min(sizeof(priv->connector.eld), len));
115802efac0fSRussell King 	mutex_unlock(&priv->audio_mutex);
1159ad975f93SRussell King 
116002efac0fSRussell King 	return 0;
1161ad975f93SRussell King }
1162ad975f93SRussell King 
1163ad975f93SRussell King static const struct hdmi_codec_ops audio_codec_ops = {
1164ad975f93SRussell King 	.hw_params = tda998x_audio_hw_params,
1165ad975f93SRussell King 	.audio_shutdown = tda998x_audio_shutdown,
1166d789710fSKuninori Morimoto 	.mute_stream = tda998x_audio_mute_stream,
1167ad975f93SRussell King 	.get_eld = tda998x_audio_get_eld,
1168d789710fSKuninori Morimoto 	.no_capture_mute = 1,
1169ad975f93SRussell King };
1170ad975f93SRussell King 
tda998x_audio_codec_init(struct tda998x_priv * priv,struct device * dev)1171ad975f93SRussell King static int tda998x_audio_codec_init(struct tda998x_priv *priv,
1172ad975f93SRussell King 				    struct device *dev)
1173ad975f93SRussell King {
1174ad975f93SRussell King 	struct hdmi_codec_pdata codec_data = {
1175ad975f93SRussell King 		.ops = &audio_codec_ops,
1176ad975f93SRussell King 		.max_i2s_channels = 2,
1177a04f1c81SMark Brown 		.no_i2s_capture = 1,
1178a04f1c81SMark Brown 		.no_spdif_capture = 1,
1179ad975f93SRussell King 	};
1180ad975f93SRussell King 
118171689160SRussell King 	if (priv->audio_port_enable[AUDIO_ROUTE_I2S])
1182ad975f93SRussell King 		codec_data.i2s = 1;
118371689160SRussell King 	if (priv->audio_port_enable[AUDIO_ROUTE_SPDIF])
1184ad975f93SRussell King 		codec_data.spdif = 1;
1185ad975f93SRussell King 
1186ad975f93SRussell King 	priv->audio_pdev = platform_device_register_data(
1187ad975f93SRussell King 		dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
1188ad975f93SRussell King 		&codec_data, sizeof(codec_data));
1189ad975f93SRussell King 
1190ad975f93SRussell King 	return PTR_ERR_OR_ZERO(priv->audio_pdev);
1191ad975f93SRussell King }
1192ad975f93SRussell King 
119325576733SRussell King /* DRM connector functions */
119425576733SRussell King 
119525576733SRussell King static enum drm_connector_status
tda998x_connector_detect(struct drm_connector * connector,bool force)119625576733SRussell King tda998x_connector_detect(struct drm_connector *connector, bool force)
119725576733SRussell King {
119825576733SRussell King 	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
119925576733SRussell King 	u8 val = cec_read(priv, REG_CEC_RXSHPDLEV);
120025576733SRussell King 
120125576733SRussell King 	return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
120225576733SRussell King 			connector_status_disconnected;
120325576733SRussell King }
120425576733SRussell King 
tda998x_connector_destroy(struct drm_connector * connector)120525576733SRussell King static void tda998x_connector_destroy(struct drm_connector *connector)
120625576733SRussell King {
120725576733SRussell King 	drm_connector_cleanup(connector);
120825576733SRussell King }
120925576733SRussell King 
121025576733SRussell King static const struct drm_connector_funcs tda998x_connector_funcs = {
121125576733SRussell King 	.reset = drm_atomic_helper_connector_reset,
1212a3d335f5SRussell King 	.fill_modes = drm_helper_probe_single_connector_modes,
121325576733SRussell King 	.detect = tda998x_connector_detect,
121425576733SRussell King 	.destroy = tda998x_connector_destroy,
121525576733SRussell King 	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
121625576733SRussell King 	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
121725576733SRussell King };
121825576733SRussell King 
read_edid_block(void * data,u8 * buf,unsigned int blk,size_t length)121925576733SRussell King static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length)
122025576733SRussell King {
122125576733SRussell King 	struct tda998x_priv *priv = data;
122225576733SRussell King 	u8 offset, segptr;
122325576733SRussell King 	int ret, i;
122425576733SRussell King 
122525576733SRussell King 	offset = (blk & 1) ? 128 : 0;
122625576733SRussell King 	segptr = blk / 2;
122725576733SRussell King 
12287e8675f0SRussell King 	mutex_lock(&priv->edid_mutex);
12297e8675f0SRussell King 
123025576733SRussell King 	reg_write(priv, REG_DDC_ADDR, 0xa0);
123125576733SRussell King 	reg_write(priv, REG_DDC_OFFS, offset);
123225576733SRussell King 	reg_write(priv, REG_DDC_SEGM_ADDR, 0x60);
123325576733SRussell King 	reg_write(priv, REG_DDC_SEGM, segptr);
123425576733SRussell King 
123525576733SRussell King 	/* enable reading EDID: */
123625576733SRussell King 	priv->wq_edid_wait = 1;
123725576733SRussell King 	reg_write(priv, REG_EDID_CTRL, 0x1);
123825576733SRussell King 
123925576733SRussell King 	/* flag must be cleared by sw: */
124025576733SRussell King 	reg_write(priv, REG_EDID_CTRL, 0x0);
124125576733SRussell King 
124225576733SRussell King 	/* wait for block read to complete: */
124325576733SRussell King 	if (priv->hdmi->irq) {
124425576733SRussell King 		i = wait_event_timeout(priv->wq_edid,
124525576733SRussell King 					!priv->wq_edid_wait,
124625576733SRussell King 					msecs_to_jiffies(100));
124725576733SRussell King 		if (i < 0) {
124825576733SRussell King 			dev_err(&priv->hdmi->dev, "read edid wait err %d\n", i);
12497e8675f0SRussell King 			ret = i;
12507e8675f0SRussell King 			goto failed;
125125576733SRussell King 		}
125225576733SRussell King 	} else {
125325576733SRussell King 		for (i = 100; i > 0; i--) {
125425576733SRussell King 			msleep(1);
125525576733SRussell King 			ret = reg_read(priv, REG_INT_FLAGS_2);
125625576733SRussell King 			if (ret < 0)
12577e8675f0SRussell King 				goto failed;
125825576733SRussell King 			if (ret & INT_FLAGS_2_EDID_BLK_RD)
125925576733SRussell King 				break;
126025576733SRussell King 		}
126125576733SRussell King 	}
126225576733SRussell King 
126325576733SRussell King 	if (i == 0) {
126425576733SRussell King 		dev_err(&priv->hdmi->dev, "read edid timeout\n");
12657e8675f0SRussell King 		ret = -ETIMEDOUT;
12667e8675f0SRussell King 		goto failed;
126725576733SRussell King 	}
126825576733SRussell King 
126925576733SRussell King 	ret = reg_read_range(priv, REG_EDID_DATA_0, buf, length);
127025576733SRussell King 	if (ret != length) {
127125576733SRussell King 		dev_err(&priv->hdmi->dev, "failed to read edid block %d: %d\n",
127225576733SRussell King 			blk, ret);
12737e8675f0SRussell King 		goto failed;
127425576733SRussell King 	}
127525576733SRussell King 
12767e8675f0SRussell King 	ret = 0;
12777e8675f0SRussell King 
12787e8675f0SRussell King  failed:
12797e8675f0SRussell King 	mutex_unlock(&priv->edid_mutex);
12807e8675f0SRussell King 	return ret;
128125576733SRussell King }
128225576733SRussell King 
tda998x_connector_get_modes(struct drm_connector * connector)128325576733SRussell King static int tda998x_connector_get_modes(struct drm_connector *connector)
128425576733SRussell King {
128525576733SRussell King 	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
1286*78e90e00SJani Nikula 	const struct drm_edid *drm_edid;
128725576733SRussell King 	int n;
128825576733SRussell King 
128925576733SRussell King 	/*
129025576733SRussell King 	 * If we get killed while waiting for the HPD timeout, return
129125576733SRussell King 	 * no modes found: we are not in a restartable path, so we
129225576733SRussell King 	 * can't handle signals gracefully.
129325576733SRussell King 	 */
129425576733SRussell King 	if (tda998x_edid_delay_wait(priv))
129525576733SRussell King 		return 0;
129625576733SRussell King 
129725576733SRussell King 	if (priv->rev == TDA19988)
129825576733SRussell King 		reg_clear(priv, REG_TX4, TX4_PD_RAM);
129925576733SRussell King 
1300*78e90e00SJani Nikula 	drm_edid = drm_edid_read_custom(connector, read_edid_block, priv);
130125576733SRussell King 
130225576733SRussell King 	if (priv->rev == TDA19988)
130325576733SRussell King 		reg_set(priv, REG_TX4, TX4_PD_RAM);
130425576733SRussell King 
1305*78e90e00SJani Nikula 	drm_edid_connector_update(connector, drm_edid);
1306*78e90e00SJani Nikula 	cec_notifier_set_phys_addr(priv->cec_notify,
1307*78e90e00SJani Nikula 				   connector->display_info.source_physical_address);
1308*78e90e00SJani Nikula 
1309*78e90e00SJani Nikula 	if (!drm_edid) {
131025576733SRussell King 		dev_warn(&priv->hdmi->dev, "failed to read EDID\n");
131125576733SRussell King 		return 0;
131225576733SRussell King 	}
131325576733SRussell King 
1314a3d335f5SRussell King 	mutex_lock(&priv->audio_mutex);
1315*78e90e00SJani Nikula 	n = drm_edid_connector_add_modes(connector);
1316*78e90e00SJani Nikula 	priv->sink_has_audio = connector->display_info.has_audio;
1317a3d335f5SRussell King 	mutex_unlock(&priv->audio_mutex);
131825576733SRussell King 
1319*78e90e00SJani Nikula 	drm_edid_free(drm_edid);
132025576733SRussell King 
132125576733SRussell King 	return n;
132225576733SRussell King }
132325576733SRussell King 
132425576733SRussell King static struct drm_encoder *
tda998x_connector_best_encoder(struct drm_connector * connector)132525576733SRussell King tda998x_connector_best_encoder(struct drm_connector *connector)
132625576733SRussell King {
132725576733SRussell King 	struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
132825576733SRussell King 
132930bd8b86SRussell King 	return priv->bridge.encoder;
133025576733SRussell King }
133125576733SRussell King 
133225576733SRussell King static
133325576733SRussell King const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = {
133425576733SRussell King 	.get_modes = tda998x_connector_get_modes,
133525576733SRussell King 	.best_encoder = tda998x_connector_best_encoder,
133625576733SRussell King };
133725576733SRussell King 
tda998x_connector_init(struct tda998x_priv * priv,struct drm_device * drm)1338a2f75662SRussell King static int tda998x_connector_init(struct tda998x_priv *priv,
1339a2f75662SRussell King 				  struct drm_device *drm)
1340a2f75662SRussell King {
1341a2f75662SRussell King 	struct drm_connector *connector = &priv->connector;
1342a2f75662SRussell King 	int ret;
1343a2f75662SRussell King 
1344a2f75662SRussell King 	connector->interlace_allowed = 1;
1345a2f75662SRussell King 
1346a2f75662SRussell King 	if (priv->hdmi->irq)
1347a2f75662SRussell King 		connector->polled = DRM_CONNECTOR_POLL_HPD;
1348a2f75662SRussell King 	else
1349a2f75662SRussell King 		connector->polled = DRM_CONNECTOR_POLL_CONNECT |
1350a2f75662SRussell King 			DRM_CONNECTOR_POLL_DISCONNECT;
1351a2f75662SRussell King 
1352a2f75662SRussell King 	drm_connector_helper_add(connector, &tda998x_connector_helper_funcs);
1353a2f75662SRussell King 	ret = drm_connector_init(drm, connector, &tda998x_connector_funcs,
1354a2f75662SRussell King 				 DRM_MODE_CONNECTOR_HDMIA);
1355a2f75662SRussell King 	if (ret)
1356a2f75662SRussell King 		return ret;
1357a2f75662SRussell King 
1358a7ccc5a4SDave Airlie 	drm_connector_attach_encoder(&priv->connector,
135930bd8b86SRussell King 				     priv->bridge.encoder);
1360a2f75662SRussell King 
1361a2f75662SRussell King 	return 0;
1362a2f75662SRussell King }
1363a2f75662SRussell King 
136430bd8b86SRussell King /* DRM bridge functions */
1365e7792ce2SRob Clark 
tda998x_bridge_attach(struct drm_bridge * bridge,enum drm_bridge_attach_flags flags)1366a25b988fSLaurent Pinchart static int tda998x_bridge_attach(struct drm_bridge *bridge,
1367a25b988fSLaurent Pinchart 				 enum drm_bridge_attach_flags flags)
1368e7792ce2SRob Clark {
136930bd8b86SRussell King 	struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
13709525c4ddSRussell King 
1371a25b988fSLaurent Pinchart 	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
1372a25b988fSLaurent Pinchart 		DRM_ERROR("Fix bridge driver to make connector optional!");
1373a25b988fSLaurent Pinchart 		return -EINVAL;
1374a25b988fSLaurent Pinchart 	}
1375a25b988fSLaurent Pinchart 
137630bd8b86SRussell King 	return tda998x_connector_init(priv, bridge->dev);
137730bd8b86SRussell King }
1378e7792ce2SRob Clark 
tda998x_bridge_detach(struct drm_bridge * bridge)137930bd8b86SRussell King static void tda998x_bridge_detach(struct drm_bridge *bridge)
138030bd8b86SRussell King {
138130bd8b86SRussell King 	struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
1382e7792ce2SRob Clark 
138330bd8b86SRussell King 	drm_connector_cleanup(&priv->connector);
138430bd8b86SRussell King }
138530bd8b86SRussell King 
tda998x_bridge_mode_valid(struct drm_bridge * bridge,const struct drm_display_info * info,const struct drm_display_mode * mode)1386b073a70eSRussell King static enum drm_mode_status tda998x_bridge_mode_valid(struct drm_bridge *bridge,
138712c683e1SLaurent Pinchart 				     const struct drm_display_info *info,
1388b073a70eSRussell King 				     const struct drm_display_mode *mode)
1389b073a70eSRussell King {
1390b073a70eSRussell King 	/* TDA19988 dotclock can go up to 165MHz */
1391b073a70eSRussell King 	struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
1392b073a70eSRussell King 
1393b073a70eSRussell King 	if (mode->clock > ((priv->rev == TDA19988) ? 165000 : 150000))
1394b073a70eSRussell King 		return MODE_CLOCK_HIGH;
1395b073a70eSRussell King 	if (mode->htotal >= BIT(13))
1396b073a70eSRussell King 		return MODE_BAD_HVALUE;
1397b073a70eSRussell King 	if (mode->vtotal >= BIT(11))
1398b073a70eSRussell King 		return MODE_BAD_VVALUE;
1399b073a70eSRussell King 	return MODE_OK;
1400b073a70eSRussell King }
1401b073a70eSRussell King 
tda998x_bridge_enable(struct drm_bridge * bridge)140230bd8b86SRussell King static void tda998x_bridge_enable(struct drm_bridge *bridge)
140330bd8b86SRussell King {
140430bd8b86SRussell King 	struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
140530bd8b86SRussell King 
14062c6e7583SPeter Rosin 	if (!priv->is_on) {
1407c4c11dd1SRussell King 		/* enable video ports, audio will be enabled later */
14082f7f730aSJean-Francois Moine 		reg_write(priv, REG_ENA_VP_0, 0xff);
14092f7f730aSJean-Francois Moine 		reg_write(priv, REG_ENA_VP_1, 0xff);
14102f7f730aSJean-Francois Moine 		reg_write(priv, REG_ENA_VP_2, 0xff);
1411e7792ce2SRob Clark 		/* set muxing after enabling ports: */
14122f7f730aSJean-Francois Moine 		reg_write(priv, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
14132f7f730aSJean-Francois Moine 		reg_write(priv, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
14142f7f730aSJean-Francois Moine 		reg_write(priv, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
14153cb43378SRussell King 
14163cb43378SRussell King 		priv->is_on = true;
14172c6e7583SPeter Rosin 	}
14182c6e7583SPeter Rosin }
14192c6e7583SPeter Rosin 
tda998x_bridge_disable(struct drm_bridge * bridge)142030bd8b86SRussell King static void tda998x_bridge_disable(struct drm_bridge *bridge)
14212c6e7583SPeter Rosin {
142230bd8b86SRussell King 	struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
142330bd8b86SRussell King 
14242c6e7583SPeter Rosin 	if (priv->is_on) {
1425db6aaf4dSRussell King 		/* disable video ports */
14262f7f730aSJean-Francois Moine 		reg_write(priv, REG_ENA_VP_0, 0x00);
14272f7f730aSJean-Francois Moine 		reg_write(priv, REG_ENA_VP_1, 0x00);
14282f7f730aSJean-Francois Moine 		reg_write(priv, REG_ENA_VP_2, 0x00);
1429e7792ce2SRob Clark 
14303cb43378SRussell King 		priv->is_on = false;
14313cb43378SRussell King 	}
1432e7792ce2SRob Clark }
1433e7792ce2SRob Clark 
tda998x_bridge_mode_set(struct drm_bridge * bridge,const struct drm_display_mode * mode,const struct drm_display_mode * adjusted_mode)143430bd8b86SRussell King static void tda998x_bridge_mode_set(struct drm_bridge *bridge,
143563f8f3baSLaurent Pinchart 				    const struct drm_display_mode *mode,
143663f8f3baSLaurent Pinchart 				    const struct drm_display_mode *adjusted_mode)
1437e7792ce2SRob Clark {
143830bd8b86SRussell King 	struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
1439926a299cSRussell King 	unsigned long tmds_clock;
1440e66e03abSRussell King 	u16 ref_pix, ref_line, n_pix, n_line;
1441e66e03abSRussell King 	u16 hs_pix_s, hs_pix_e;
1442e66e03abSRussell King 	u16 vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e;
1443e66e03abSRussell King 	u16 vs2_pix_s, vs2_pix_e, vs2_line_s, vs2_line_e;
1444e66e03abSRussell King 	u16 vwin1_line_s, vwin1_line_e;
1445e66e03abSRussell King 	u16 vwin2_line_s, vwin2_line_e;
1446e66e03abSRussell King 	u16 de_pix_s, de_pix_e;
14472807ba75SRussell King 	u8 reg, div, rep, sel_clk;
1448e7792ce2SRob Clark 
1449088d61d1SSebastian Hesselbarth 	/*
1450fcc22c5fSRussell King 	 * Since we are "computer" like, our source invariably produces
1451fcc22c5fSRussell King 	 * full-range RGB.  If the monitor supports full-range, then use
1452fcc22c5fSRussell King 	 * it, otherwise reduce to limited-range.
1453fcc22c5fSRussell King 	 */
1454fcc22c5fSRussell King 	priv->rgb_quant_range =
1455fcc22c5fSRussell King 		priv->connector.display_info.rgb_quant_range_selectable ?
1456fcc22c5fSRussell King 		HDMI_QUANTIZATION_RANGE_FULL :
1457fcc22c5fSRussell King 		drm_default_rgb_quant_range(adjusted_mode);
1458e7792ce2SRob Clark 
1459088d61d1SSebastian Hesselbarth 	/*
1460088d61d1SSebastian Hesselbarth 	 * Internally TDA998x is using ITU-R BT.656 style sync but
1461088d61d1SSebastian Hesselbarth 	 * we get VESA style sync. TDA998x is using a reference pixel
1462088d61d1SSebastian Hesselbarth 	 * relative to ITU to sync to the input frame and for output
1463088d61d1SSebastian Hesselbarth 	 * sync generation. Currently, we are using reference detection
1464088d61d1SSebastian Hesselbarth 	 * from HS/VS, i.e. REFPIX/REFLINE denote frame start sync point
1465088d61d1SSebastian Hesselbarth 	 * which is position of rising VS with coincident rising HS.
1466088d61d1SSebastian Hesselbarth 	 *
1467088d61d1SSebastian Hesselbarth 	 * Now there is some issues to take care of:
1468088d61d1SSebastian Hesselbarth 	 * - HDMI data islands require sync-before-active
1469088d61d1SSebastian Hesselbarth 	 * - TDA998x register values must be > 0 to be enabled
1470088d61d1SSebastian Hesselbarth 	 * - REFLINE needs an additional offset of +1
1471088d61d1SSebastian Hesselbarth 	 * - REFPIX needs an addtional offset of +1 for UYUV and +3 for RGB
1472088d61d1SSebastian Hesselbarth 	 *
1473088d61d1SSebastian Hesselbarth 	 * So we add +1 to all horizontal and vertical register values,
1474088d61d1SSebastian Hesselbarth 	 * plus an additional +3 for REFPIX as we are using RGB input only.
1475e7792ce2SRob Clark 	 */
1476088d61d1SSebastian Hesselbarth 	n_pix        = mode->htotal;
1477088d61d1SSebastian Hesselbarth 	n_line       = mode->vtotal;
1478e7792ce2SRob Clark 
1479088d61d1SSebastian Hesselbarth 	hs_pix_e     = mode->hsync_end - mode->hdisplay;
1480088d61d1SSebastian Hesselbarth 	hs_pix_s     = mode->hsync_start - mode->hdisplay;
1481088d61d1SSebastian Hesselbarth 	de_pix_e     = mode->htotal;
1482088d61d1SSebastian Hesselbarth 	de_pix_s     = mode->htotal - mode->hdisplay;
1483088d61d1SSebastian Hesselbarth 	ref_pix      = 3 + hs_pix_s;
1484088d61d1SSebastian Hesselbarth 
1485179f1aa4SSebastian Hesselbarth 	/*
1486179f1aa4SSebastian Hesselbarth 	 * Attached LCD controllers may generate broken sync. Allow
1487179f1aa4SSebastian Hesselbarth 	 * those to adjust the position of the rising VS edge by adding
1488179f1aa4SSebastian Hesselbarth 	 * HSKEW to ref_pix.
1489179f1aa4SSebastian Hesselbarth 	 */
1490179f1aa4SSebastian Hesselbarth 	if (adjusted_mode->flags & DRM_MODE_FLAG_HSKEW)
1491179f1aa4SSebastian Hesselbarth 		ref_pix += adjusted_mode->hskew;
1492179f1aa4SSebastian Hesselbarth 
1493088d61d1SSebastian Hesselbarth 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) {
1494088d61d1SSebastian Hesselbarth 		ref_line     = 1 + mode->vsync_start - mode->vdisplay;
1495088d61d1SSebastian Hesselbarth 		vwin1_line_s = mode->vtotal - mode->vdisplay - 1;
1496088d61d1SSebastian Hesselbarth 		vwin1_line_e = vwin1_line_s + mode->vdisplay;
1497088d61d1SSebastian Hesselbarth 		vs1_pix_s    = vs1_pix_e = hs_pix_s;
1498088d61d1SSebastian Hesselbarth 		vs1_line_s   = mode->vsync_start - mode->vdisplay;
1499088d61d1SSebastian Hesselbarth 		vs1_line_e   = vs1_line_s +
1500088d61d1SSebastian Hesselbarth 			       mode->vsync_end - mode->vsync_start;
1501088d61d1SSebastian Hesselbarth 		vwin2_line_s = vwin2_line_e = 0;
1502088d61d1SSebastian Hesselbarth 		vs2_pix_s    = vs2_pix_e  = 0;
1503088d61d1SSebastian Hesselbarth 		vs2_line_s   = vs2_line_e = 0;
1504088d61d1SSebastian Hesselbarth 	} else {
1505088d61d1SSebastian Hesselbarth 		ref_line     = 1 + (mode->vsync_start - mode->vdisplay)/2;
1506088d61d1SSebastian Hesselbarth 		vwin1_line_s = (mode->vtotal - mode->vdisplay)/2;
1507088d61d1SSebastian Hesselbarth 		vwin1_line_e = vwin1_line_s + mode->vdisplay/2;
1508088d61d1SSebastian Hesselbarth 		vs1_pix_s    = vs1_pix_e = hs_pix_s;
1509088d61d1SSebastian Hesselbarth 		vs1_line_s   = (mode->vsync_start - mode->vdisplay)/2;
1510088d61d1SSebastian Hesselbarth 		vs1_line_e   = vs1_line_s +
1511088d61d1SSebastian Hesselbarth 			       (mode->vsync_end - mode->vsync_start)/2;
1512088d61d1SSebastian Hesselbarth 		vwin2_line_s = vwin1_line_s + mode->vtotal/2;
1513088d61d1SSebastian Hesselbarth 		vwin2_line_e = vwin2_line_s + mode->vdisplay/2;
1514088d61d1SSebastian Hesselbarth 		vs2_pix_s    = vs2_pix_e = hs_pix_s + mode->htotal/2;
1515088d61d1SSebastian Hesselbarth 		vs2_line_s   = vs1_line_s + mode->vtotal/2 ;
1516088d61d1SSebastian Hesselbarth 		vs2_line_e   = vs2_line_s +
1517088d61d1SSebastian Hesselbarth 			       (mode->vsync_end - mode->vsync_start)/2;
1518088d61d1SSebastian Hesselbarth 	}
1519e7792ce2SRob Clark 
15202807ba75SRussell King 	/*
15212807ba75SRussell King 	 * Select pixel repeat depending on the double-clock flag
15222807ba75SRussell King 	 * (which means we have to repeat each pixel once.)
15232807ba75SRussell King 	 */
15242807ba75SRussell King 	rep = mode->flags & DRM_MODE_FLAG_DBLCLK ? 1 : 0;
15252807ba75SRussell King 	sel_clk = SEL_CLK_ENA_SC_CLK | SEL_CLK_SEL_CLK1 |
15262807ba75SRussell King 		  SEL_CLK_SEL_VRF_CLK(rep ? 2 : 0);
15272807ba75SRussell King 
15282807ba75SRussell King 	/* the TMDS clock is scaled up by the pixel repeat */
15292807ba75SRussell King 	tmds_clock = mode->clock * (1 + rep);
1530926a299cSRussell King 
1531926a299cSRussell King 	/*
1532926a299cSRussell King 	 * The divisor is power-of-2. The TDA9983B datasheet gives
1533926a299cSRussell King 	 * this as ranges of Msample/s, which is 10x the TMDS clock:
1534926a299cSRussell King 	 *   0 - 800 to 1500 Msample/s
1535926a299cSRussell King 	 *   1 - 400 to 800 Msample/s
1536926a299cSRussell King 	 *   2 - 200 to 400 Msample/s
1537926a299cSRussell King 	 *   3 - as 2 above
1538926a299cSRussell King 	 */
1539926a299cSRussell King 	for (div = 0; div < 3; div++)
1540926a299cSRussell King 		if (80000 >> div <= tmds_clock)
1541926a299cSRussell King 			break;
1542e7792ce2SRob Clark 
15432cae8e02SRussell King 	mutex_lock(&priv->audio_mutex);
15442cae8e02SRussell King 
15452807ba75SRussell King 	priv->tmds_clock = tmds_clock;
15462807ba75SRussell King 
1547e7792ce2SRob Clark 	/* mute the audio FIFO: */
15482f7f730aSJean-Francois Moine 	reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
1549e7792ce2SRob Clark 
1550e7792ce2SRob Clark 	/* set HDMI HDCP mode off: */
155181b53a16SJean-Francois Moine 	reg_write(priv, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
15522f7f730aSJean-Francois Moine 	reg_clear(priv, REG_TX33, TX33_HDMI);
15532f7f730aSJean-Francois Moine 	reg_write(priv, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0));
1554e7792ce2SRob Clark 
1555e7792ce2SRob Clark 	/* no pre-filter or interpolator: */
15562f7f730aSJean-Francois Moine 	reg_write(priv, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
1557e7792ce2SRob Clark 			HVF_CNTRL_0_INTPOL(0));
15589476ed2eSRussell King 	reg_set(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_PREFILT);
15592f7f730aSJean-Francois Moine 	reg_write(priv, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
15602f7f730aSJean-Francois Moine 	reg_write(priv, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
1561e7792ce2SRob Clark 			VIP_CNTRL_4_BLC(0));
1562e7792ce2SRob Clark 
15632f7f730aSJean-Francois Moine 	reg_clear(priv, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ);
1564a8b517e5SJean-Francois Moine 	reg_clear(priv, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR |
1565a8b517e5SJean-Francois Moine 					  PLL_SERIAL_3_SRL_DE);
15662f7f730aSJean-Francois Moine 	reg_write(priv, REG_SERIALIZER, 0);
15672f7f730aSJean-Francois Moine 	reg_write(priv, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0));
1568e7792ce2SRob Clark 
15692807ba75SRussell King 	reg_write(priv, REG_RPT_CNTRL, RPT_CNTRL_REPEAT(rep));
15702807ba75SRussell King 	reg_write(priv, REG_SEL_CLK, sel_clk);
15712f7f730aSJean-Francois Moine 	reg_write(priv, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
1572e7792ce2SRob Clark 			PLL_SERIAL_2_SRL_PR(rep));
1573e7792ce2SRob Clark 
1574fcc22c5fSRussell King 	/* set color matrix according to output rgb quant range */
1575fcc22c5fSRussell King 	if (priv->rgb_quant_range == HDMI_QUANTIZATION_RANGE_LIMITED) {
1576fcc22c5fSRussell King 		static u8 tda998x_full_to_limited_range[] = {
1577fcc22c5fSRussell King 			MAT_CONTRL_MAT_SC(2),
1578fcc22c5fSRussell King 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1579fcc22c5fSRussell King 			0x03, 0x6f, 0x00, 0x00, 0x00, 0x00,
1580fcc22c5fSRussell King 			0x00, 0x00, 0x03, 0x6f, 0x00, 0x00,
1581fcc22c5fSRussell King 			0x00, 0x00, 0x00, 0x00, 0x03, 0x6f,
1582fcc22c5fSRussell King 			0x00, 0x40, 0x00, 0x40, 0x00, 0x40
1583fcc22c5fSRussell King 		};
1584fcc22c5fSRussell King 		reg_clear(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_CSC);
1585fcc22c5fSRussell King 		reg_write_range(priv, REG_MAT_CONTRL,
1586fcc22c5fSRussell King 				tda998x_full_to_limited_range,
1587fcc22c5fSRussell King 				sizeof(tda998x_full_to_limited_range));
1588fcc22c5fSRussell King 	} else {
158981b53a16SJean-Francois Moine 		reg_write(priv, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP |
159081b53a16SJean-Francois Moine 					MAT_CONTRL_MAT_SC(1));
15919476ed2eSRussell King 		reg_set(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_CSC);
1592fcc22c5fSRussell King 	}
1593e7792ce2SRob Clark 
1594e7792ce2SRob Clark 	/* set BIAS tmds value: */
15952f7f730aSJean-Francois Moine 	reg_write(priv, REG_ANA_GENERAL, 0x09);
1596e7792ce2SRob Clark 
1597088d61d1SSebastian Hesselbarth 	/*
1598088d61d1SSebastian Hesselbarth 	 * Sync on rising HSYNC/VSYNC
1599088d61d1SSebastian Hesselbarth 	 */
160081b53a16SJean-Francois Moine 	reg = VIP_CNTRL_3_SYNC_HS;
1601088d61d1SSebastian Hesselbarth 
1602088d61d1SSebastian Hesselbarth 	/*
1603088d61d1SSebastian Hesselbarth 	 * TDA19988 requires high-active sync at input stage,
1604088d61d1SSebastian Hesselbarth 	 * so invert low-active sync provided by master encoder here
1605088d61d1SSebastian Hesselbarth 	 */
1606088d61d1SSebastian Hesselbarth 	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
160781b53a16SJean-Francois Moine 		reg |= VIP_CNTRL_3_H_TGL;
1608e7792ce2SRob Clark 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
160981b53a16SJean-Francois Moine 		reg |= VIP_CNTRL_3_V_TGL;
161081b53a16SJean-Francois Moine 	reg_write(priv, REG_VIP_CNTRL_3, reg);
1611e7792ce2SRob Clark 
16122f7f730aSJean-Francois Moine 	reg_write(priv, REG_VIDFORMAT, 0x00);
16132f7f730aSJean-Francois Moine 	reg_write16(priv, REG_REFPIX_MSB, ref_pix);
16142f7f730aSJean-Francois Moine 	reg_write16(priv, REG_REFLINE_MSB, ref_line);
16152f7f730aSJean-Francois Moine 	reg_write16(priv, REG_NPIX_MSB, n_pix);
16162f7f730aSJean-Francois Moine 	reg_write16(priv, REG_NLINE_MSB, n_line);
16172f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VS_LINE_STRT_1_MSB, vs1_line_s);
16182f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VS_PIX_STRT_1_MSB, vs1_pix_s);
16192f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VS_LINE_END_1_MSB, vs1_line_e);
16202f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VS_PIX_END_1_MSB, vs1_pix_e);
16212f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VS_LINE_STRT_2_MSB, vs2_line_s);
16222f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VS_PIX_STRT_2_MSB, vs2_pix_s);
16232f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VS_LINE_END_2_MSB, vs2_line_e);
16242f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VS_PIX_END_2_MSB, vs2_pix_e);
16252f7f730aSJean-Francois Moine 	reg_write16(priv, REG_HS_PIX_START_MSB, hs_pix_s);
16262f7f730aSJean-Francois Moine 	reg_write16(priv, REG_HS_PIX_STOP_MSB, hs_pix_e);
16272f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VWIN_START_1_MSB, vwin1_line_s);
16282f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VWIN_END_1_MSB, vwin1_line_e);
16292f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VWIN_START_2_MSB, vwin2_line_s);
16302f7f730aSJean-Francois Moine 	reg_write16(priv, REG_VWIN_END_2_MSB, vwin2_line_e);
16312f7f730aSJean-Francois Moine 	reg_write16(priv, REG_DE_START_MSB, de_pix_s);
16322f7f730aSJean-Francois Moine 	reg_write16(priv, REG_DE_STOP_MSB, de_pix_e);
1633e7792ce2SRob Clark 
1634e7792ce2SRob Clark 	if (priv->rev == TDA19988) {
1635e7792ce2SRob Clark 		/* let incoming pixels fill the active space (if any) */
16362f7f730aSJean-Francois Moine 		reg_write(priv, REG_ENABLE_SPACE, 0x00);
1637e7792ce2SRob Clark 	}
1638e7792ce2SRob Clark 
163981b53a16SJean-Francois Moine 	/*
164081b53a16SJean-Francois Moine 	 * Always generate sync polarity relative to input sync and
164181b53a16SJean-Francois Moine 	 * revert input stage toggled sync at output stage
164281b53a16SJean-Francois Moine 	 */
164381b53a16SJean-Francois Moine 	reg = TBG_CNTRL_1_DWIN_DIS | TBG_CNTRL_1_TGL_EN;
164481b53a16SJean-Francois Moine 	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
164581b53a16SJean-Francois Moine 		reg |= TBG_CNTRL_1_H_TGL;
164681b53a16SJean-Francois Moine 	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
164781b53a16SJean-Francois Moine 		reg |= TBG_CNTRL_1_V_TGL;
164881b53a16SJean-Francois Moine 	reg_write(priv, REG_TBG_CNTRL_1, reg);
164981b53a16SJean-Francois Moine 
1650e7792ce2SRob Clark 	/* must be last register set: */
165181b53a16SJean-Francois Moine 	reg_write(priv, REG_TBG_CNTRL_0, 0);
1652c4c11dd1SRussell King 
1653896a4130SRussell King 	/* CEA-861B section 6 says that:
1654896a4130SRussell King 	 * CEA version 1 (CEA-861) has no support for infoframes.
1655896a4130SRussell King 	 * CEA version 2 (CEA-861A) supports version 1 AVI infoframes,
1656896a4130SRussell King 	 * and optional basic audio.
1657896a4130SRussell King 	 * CEA version 3 (CEA-861B) supports version 1 and 2 AVI infoframes,
1658896a4130SRussell King 	 * and optional digital audio, with audio infoframes.
1659896a4130SRussell King 	 *
1660896a4130SRussell King 	 * Since we only support generation of version 2 AVI infoframes,
1661896a4130SRussell King 	 * ignore CEA version 2 and below (iow, behave as if we're a
1662896a4130SRussell King 	 * CEA-861 source.)
1663896a4130SRussell King 	 */
1664896a4130SRussell King 	priv->supports_infoframes = priv->connector.display_info.cea_rev >= 3;
1665896a4130SRussell King 
1666896a4130SRussell King 	if (priv->supports_infoframes) {
1667c4c11dd1SRussell King 		/* We need to turn HDMI HDCP stuff on to get audio through */
166881b53a16SJean-Francois Moine 		reg &= ~TBG_CNTRL_1_DWIN_DIS;
166981b53a16SJean-Francois Moine 		reg_write(priv, REG_TBG_CNTRL_1, reg);
16702f7f730aSJean-Francois Moine 		reg_write(priv, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(1));
16712f7f730aSJean-Francois Moine 		reg_set(priv, REG_TX33, TX33_HDMI);
1672c4c11dd1SRussell King 
16732f7f730aSJean-Francois Moine 		tda998x_write_avi(priv, adjusted_mode);
167445a19dd3SRussell King 		tda998x_write_vsi(priv, adjusted_mode);
1675c4c11dd1SRussell King 
167682642ab7SRussell King 		if (priv->sink_has_audio)
1677900b2b72SRussell King 			tda998x_configure_audio(priv);
167895db3b25SJyri Sarha 	}
1679319e658cSRussell King 
1680319e658cSRussell King 	mutex_unlock(&priv->audio_mutex);
1681c4c11dd1SRussell King }
1682e7792ce2SRob Clark 
168330bd8b86SRussell King static const struct drm_bridge_funcs tda998x_bridge_funcs = {
168430bd8b86SRussell King 	.attach = tda998x_bridge_attach,
168530bd8b86SRussell King 	.detach = tda998x_bridge_detach,
1686b073a70eSRussell King 	.mode_valid = tda998x_bridge_mode_valid,
168730bd8b86SRussell King 	.disable = tda998x_bridge_disable,
168830bd8b86SRussell King 	.mode_set = tda998x_bridge_mode_set,
168930bd8b86SRussell King 	.enable = tda998x_bridge_enable,
169030bd8b86SRussell King };
1691a8f4d4d6SRussell King 
1692e7792ce2SRob Clark /* I2C driver functions */
1693e7792ce2SRob Clark 
tda998x_get_audio_ports(struct tda998x_priv * priv,struct device_node * np)16947e567624SJyri Sarha static int tda998x_get_audio_ports(struct tda998x_priv *priv,
16957e567624SJyri Sarha 				   struct device_node *np)
16967e567624SJyri Sarha {
16977e567624SJyri Sarha 	const u32 *port_data;
16987e567624SJyri Sarha 	u32 size;
16997e567624SJyri Sarha 	int i;
17007e567624SJyri Sarha 
17017e567624SJyri Sarha 	port_data = of_get_property(np, "audio-ports", &size);
17027e567624SJyri Sarha 	if (!port_data)
17037e567624SJyri Sarha 		return 0;
17047e567624SJyri Sarha 
17057e567624SJyri Sarha 	size /= sizeof(u32);
170671689160SRussell King 	if (size > 2 * ARRAY_SIZE(priv->audio_port_enable) || size % 2 != 0) {
17077e567624SJyri Sarha 		dev_err(&priv->hdmi->dev,
17087e567624SJyri Sarha 			"Bad number of elements in audio-ports dt-property\n");
17097e567624SJyri Sarha 		return -EINVAL;
17107e567624SJyri Sarha 	}
17117e567624SJyri Sarha 
17127e567624SJyri Sarha 	size /= 2;
17137e567624SJyri Sarha 
17147e567624SJyri Sarha 	for (i = 0; i < size; i++) {
171571689160SRussell King 		unsigned int route;
17167e567624SJyri Sarha 		u8 afmt = be32_to_cpup(&port_data[2*i]);
17177e567624SJyri Sarha 		u8 ena_ap = be32_to_cpup(&port_data[2*i+1]);
17187e567624SJyri Sarha 
171971689160SRussell King 		switch (afmt) {
172071689160SRussell King 		case AFMT_I2S:
172171689160SRussell King 			route = AUDIO_ROUTE_I2S;
172271689160SRussell King 			break;
172371689160SRussell King 		case AFMT_SPDIF:
172471689160SRussell King 			route = AUDIO_ROUTE_SPDIF;
172571689160SRussell King 			break;
172671689160SRussell King 		default:
17277e567624SJyri Sarha 			dev_err(&priv->hdmi->dev,
17287e567624SJyri Sarha 				"Bad audio format %u\n", afmt);
17297e567624SJyri Sarha 			return -EINVAL;
17307e567624SJyri Sarha 		}
17317e567624SJyri Sarha 
1732125a4f93SRussell King 		if (!ena_ap) {
1733125a4f93SRussell King 			dev_err(&priv->hdmi->dev, "invalid zero port config\n");
1734125a4f93SRussell King 			continue;
17357e567624SJyri Sarha 		}
17367e567624SJyri Sarha 
173771689160SRussell King 		if (priv->audio_port_enable[route]) {
17387e567624SJyri Sarha 			dev_err(&priv->hdmi->dev,
1739125a4f93SRussell King 				"%s format already configured\n",
1740125a4f93SRussell King 				route == AUDIO_ROUTE_SPDIF ? "SPDIF" : "I2S");
17417e567624SJyri Sarha 			return -EINVAL;
17427e567624SJyri Sarha 		}
174371689160SRussell King 
174471689160SRussell King 		priv->audio_port_enable[route] = ena_ap;
174571689160SRussell King 	}
17467e567624SJyri Sarha 	return 0;
17477e567624SJyri Sarha }
17487e567624SJyri Sarha 
tda998x_set_config(struct tda998x_priv * priv,const struct tda998x_encoder_params * p)1749a03a915bSRussell King static int tda998x_set_config(struct tda998x_priv *priv,
17506c1187aaSRussell King 			      const struct tda998x_encoder_params *p)
1751e7792ce2SRob Clark {
17526c1187aaSRussell King 	priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
17536c1187aaSRussell King 			    (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
17546c1187aaSRussell King 			    VIP_CNTRL_0_SWAP_B(p->swap_b) |
17556c1187aaSRussell King 			    (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
17566c1187aaSRussell King 	priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
17576c1187aaSRussell King 			    (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
17586c1187aaSRussell King 			    VIP_CNTRL_1_SWAP_D(p->swap_d) |
17596c1187aaSRussell King 			    (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
17606c1187aaSRussell King 	priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
17616c1187aaSRussell King 			    (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
17626c1187aaSRussell King 			    VIP_CNTRL_2_SWAP_F(p->swap_f) |
17636c1187aaSRussell King 			    (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
17646c1187aaSRussell King 
1765935b9ca3SRussell King 	if (p->audio_params.format != AFMT_UNUSED) {
176626f7bf12SRussell King 		unsigned int ratio, route;
1767a03a915bSRussell King 		bool spdif = p->audio_params.format == AFMT_SPDIF;
1768a03a915bSRussell King 
176926f7bf12SRussell King 		route = AUDIO_ROUTE_I2S + spdif;
177026f7bf12SRussell King 
177126f7bf12SRussell King 		priv->audio.route = &tda998x_audio_route[route];
1772125a4f93SRussell King 		priv->audio.cea = p->audio_params.cea;
1773125a4f93SRussell King 		priv->audio.sample_rate = p->audio_params.sample_rate;
1774125a4f93SRussell King 		memcpy(priv->audio.status, p->audio_params.status,
1775125a4f93SRussell King 		       min(sizeof(priv->audio.status),
1776125a4f93SRussell King 			   sizeof(p->audio_params.status)));
177782642ab7SRussell King 		priv->audio.ena_ap = p->audio_params.config;
1778935b9ca3SRussell King 		priv->audio.i2s_format = I2S_FORMAT_PHILIPS;
1779a03a915bSRussell King 
1780a03a915bSRussell King 		ratio = spdif ? 64 : p->audio_params.sample_width * 2;
1781a03a915bSRussell King 		return tda998x_derive_cts_n(priv, &priv->audio, ratio);
1782935b9ca3SRussell King 	}
1783a03a915bSRussell King 
1784a03a915bSRussell King 	return 0;
17856c1187aaSRussell King }
17866c1187aaSRussell King 
tda998x_destroy(struct device * dev)178776767fdaSRussell King static void tda998x_destroy(struct device *dev)
178876767fdaSRussell King {
178976767fdaSRussell King 	struct tda998x_priv *priv = dev_get_drvdata(dev);
179076767fdaSRussell King 
179176767fdaSRussell King 	drm_bridge_remove(&priv->bridge);
179276767fdaSRussell King 
179376767fdaSRussell King 	/* disable all IRQs and free the IRQ handler */
179476767fdaSRussell King 	cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
179576767fdaSRussell King 	reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
179676767fdaSRussell King 
179776767fdaSRussell King 	if (priv->audio_pdev)
179876767fdaSRussell King 		platform_device_unregister(priv->audio_pdev);
179976767fdaSRussell King 
180076767fdaSRussell King 	if (priv->hdmi->irq)
180176767fdaSRussell King 		free_irq(priv->hdmi->irq, priv);
180276767fdaSRussell King 
180376767fdaSRussell King 	del_timer_sync(&priv->edid_delay_timer);
180476767fdaSRussell King 	cancel_work_sync(&priv->detect_work);
180576767fdaSRussell King 
180676767fdaSRussell King 	i2c_unregister_device(priv->cec);
180776767fdaSRussell King 
1808ece485d5SDariusz Marcinkiewicz 	cec_notifier_conn_unregister(priv->cec_notify);
180976767fdaSRussell King }
181076767fdaSRussell King 
tda998x_create(struct device * dev)18112143adb0SRussell King static int tda998x_create(struct device *dev)
1812e7792ce2SRob Clark {
18132143adb0SRussell King 	struct i2c_client *client = to_i2c_client(dev);
18140d44ea19SJean-Francois Moine 	struct device_node *np = client->dev.of_node;
18157e8675f0SRussell King 	struct i2c_board_info cec_info;
18162143adb0SRussell King 	struct tda998x_priv *priv;
18170d44ea19SJean-Francois Moine 	u32 video;
1818fb7544d7SRussell King 	int rev_lo, rev_hi, ret;
1819e7792ce2SRob Clark 
18202143adb0SRussell King 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
18212143adb0SRussell King 	if (!priv)
18222143adb0SRussell King 		return -ENOMEM;
18232143adb0SRussell King 
18242143adb0SRussell King 	dev_set_drvdata(dev, priv);
18252143adb0SRussell King 
1826d93ae190SRussell King 	mutex_init(&priv->mutex);	/* protect the page access */
1827d93ae190SRussell King 	mutex_init(&priv->audio_mutex); /* protect access from audio thread */
18287e8675f0SRussell King 	mutex_init(&priv->edid_mutex);
182930bd8b86SRussell King 	INIT_LIST_HEAD(&priv->bridge.list);
1830d93ae190SRussell King 	init_waitqueue_head(&priv->edid_delay_waitq);
1831d93ae190SRussell King 	timer_setup(&priv->edid_delay_timer, tda998x_edid_delay_done, 0);
1832d93ae190SRussell King 	INIT_WORK(&priv->detect_work, tda998x_detect_work);
1833ba300c17SRussell King 
18345e74c22cSRussell King 	priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
18355e74c22cSRussell King 	priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
18365e74c22cSRussell King 	priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
18375e74c22cSRussell King 
183814e5b588SRussell King 	/* CEC I2C address bound to TDA998x I2C addr by configuration pins */
183914e5b588SRussell King 	priv->cec_addr = 0x34 + (client->addr & 0x03);
18402eb4c7b1SJean-Francois Moine 	priv->current_page = 0xff;
18412f7f730aSJean-Francois Moine 	priv->hdmi = client;
1842ed9a8426SJean-Francois Moine 
1843e7792ce2SRob Clark 	/* wake up the device: */
18442f7f730aSJean-Francois Moine 	cec_write(priv, REG_CEC_ENAMODS,
1845e7792ce2SRob Clark 			CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
1846e7792ce2SRob Clark 
18472f7f730aSJean-Francois Moine 	tda998x_reset(priv);
1848e7792ce2SRob Clark 
1849e7792ce2SRob Clark 	/* read version: */
1850fb7544d7SRussell King 	rev_lo = reg_read(priv, REG_VERSION_LSB);
18516a765c3fSRussell King 	if (rev_lo < 0) {
185276767fdaSRussell King 		dev_err(dev, "failed to read version: %d\n", rev_lo);
18536a765c3fSRussell King 		return rev_lo;
18546a765c3fSRussell King 	}
18556a765c3fSRussell King 
1856fb7544d7SRussell King 	rev_hi = reg_read(priv, REG_VERSION_MSB);
18576a765c3fSRussell King 	if (rev_hi < 0) {
185876767fdaSRussell King 		dev_err(dev, "failed to read version: %d\n", rev_hi);
18596a765c3fSRussell King 		return rev_hi;
1860fb7544d7SRussell King 	}
1861fb7544d7SRussell King 
1862fb7544d7SRussell King 	priv->rev = rev_lo | rev_hi << 8;
1863e7792ce2SRob Clark 
1864e7792ce2SRob Clark 	/* mask off feature bits: */
1865e7792ce2SRob Clark 	priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */
1866e7792ce2SRob Clark 
1867e7792ce2SRob Clark 	switch (priv->rev) {
1868b728fab7SJean-Francois Moine 	case TDA9989N2:
186976767fdaSRussell King 		dev_info(dev, "found TDA9989 n2");
1870b728fab7SJean-Francois Moine 		break;
1871b728fab7SJean-Francois Moine 	case TDA19989:
187276767fdaSRussell King 		dev_info(dev, "found TDA19989");
1873b728fab7SJean-Francois Moine 		break;
1874b728fab7SJean-Francois Moine 	case TDA19989N2:
187576767fdaSRussell King 		dev_info(dev, "found TDA19989 n2");
1876b728fab7SJean-Francois Moine 		break;
1877b728fab7SJean-Francois Moine 	case TDA19988:
187876767fdaSRussell King 		dev_info(dev, "found TDA19988");
1879b728fab7SJean-Francois Moine 		break;
1880e7792ce2SRob Clark 	default:
188176767fdaSRussell King 		dev_err(dev, "found unsupported device: %04x\n", priv->rev);
18826a765c3fSRussell King 		return -ENXIO;
1883e7792ce2SRob Clark 	}
1884e7792ce2SRob Clark 
1885e7792ce2SRob Clark 	/* after reset, enable DDC: */
18862f7f730aSJean-Francois Moine 	reg_write(priv, REG_DDC_DISABLE, 0x00);
1887e7792ce2SRob Clark 
1888e7792ce2SRob Clark 	/* set clock on DDC channel: */
18892f7f730aSJean-Francois Moine 	reg_write(priv, REG_TX3, 39);
1890e7792ce2SRob Clark 
1891e7792ce2SRob Clark 	/* if necessary, disable multi-master: */
1892e7792ce2SRob Clark 	if (priv->rev == TDA19989)
18932f7f730aSJean-Francois Moine 		reg_set(priv, REG_I2C_MASTER, I2C_MASTER_DIS_MM);
1894e7792ce2SRob Clark 
18952f7f730aSJean-Francois Moine 	cec_write(priv, REG_CEC_FRO_IM_CLK_CTRL,
1896e7792ce2SRob Clark 			CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
1897e7792ce2SRob Clark 
1898ba8975f1SRussell King 	/* ensure interrupts are disabled */
1899ba8975f1SRussell King 	cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
1900ba8975f1SRussell King 
1901ba8975f1SRussell King 	/* clear pending interrupts */
1902ba8975f1SRussell King 	cec_read(priv, REG_CEC_RXSHPDINT);
1903ba8975f1SRussell King 	reg_read(priv, REG_INT_FLAGS_0);
1904ba8975f1SRussell King 	reg_read(priv, REG_INT_FLAGS_1);
1905ba8975f1SRussell King 	reg_read(priv, REG_INT_FLAGS_2);
1906ba8975f1SRussell King 
190712473b7dSJean-Francois Moine 	/* initialize the optional IRQ */
190812473b7dSJean-Francois Moine 	if (client->irq) {
1909ae81553cSRussell King 		unsigned long irq_flags;
191012473b7dSJean-Francois Moine 
19116833d26eSJean-Francois Moine 		/* init read EDID waitqueue and HDP work */
191212473b7dSJean-Francois Moine 		init_waitqueue_head(&priv->wq_edid);
191312473b7dSJean-Francois Moine 
1914ae81553cSRussell King 		irq_flags =
191512473b7dSJean-Francois Moine 			irqd_get_trigger_type(irq_get_irq_data(client->irq));
19167e8675f0SRussell King 
19177e8675f0SRussell King 		priv->cec_glue.irq_flags = irq_flags;
19187e8675f0SRussell King 
1919ae81553cSRussell King 		irq_flags |= IRQF_SHARED | IRQF_ONESHOT;
192012473b7dSJean-Francois Moine 		ret = request_threaded_irq(client->irq, NULL,
1921ae81553cSRussell King 					   tda998x_irq_thread, irq_flags,
192212473b7dSJean-Francois Moine 					   "tda998x", priv);
192312473b7dSJean-Francois Moine 		if (ret) {
192476767fdaSRussell King 			dev_err(dev, "failed to request IRQ#%u: %d\n",
192512473b7dSJean-Francois Moine 				client->irq, ret);
19266a765c3fSRussell King 			goto err_irq;
192712473b7dSJean-Francois Moine 		}
192812473b7dSJean-Francois Moine 
192912473b7dSJean-Francois Moine 		/* enable HPD irq */
193012473b7dSJean-Francois Moine 		cec_write(priv, REG_CEC_RXSHPDINTENA, CEC_RXSHPDLEV_HPD);
193112473b7dSJean-Francois Moine 	}
193212473b7dSJean-Francois Moine 
1933ece485d5SDariusz Marcinkiewicz 	priv->cec_notify = cec_notifier_conn_register(dev, NULL, NULL);
19347e8675f0SRussell King 	if (!priv->cec_notify) {
19357e8675f0SRussell King 		ret = -ENOMEM;
19367e8675f0SRussell King 		goto fail;
19377e8675f0SRussell King 	}
19387e8675f0SRussell King 
193976767fdaSRussell King 	priv->cec_glue.parent = dev;
19407e8675f0SRussell King 	priv->cec_glue.data = priv;
19417e8675f0SRussell King 	priv->cec_glue.init = tda998x_cec_hook_init;
19427e8675f0SRussell King 	priv->cec_glue.exit = tda998x_cec_hook_exit;
19437e8675f0SRussell King 	priv->cec_glue.open = tda998x_cec_hook_open;
19447e8675f0SRussell King 	priv->cec_glue.release = tda998x_cec_hook_release;
19457e8675f0SRussell King 
19467e8675f0SRussell King 	/*
19477e8675f0SRussell King 	 * Some TDA998x are actually two I2C devices merged onto one piece
19487e8675f0SRussell King 	 * of silicon: TDA9989 and TDA19989 combine the HDMI transmitter
19497e8675f0SRussell King 	 * with a slightly modified TDA9950 CEC device.  The CEC device
19507e8675f0SRussell King 	 * is at the TDA9950 address, with the address pins strapped across
19517e8675f0SRussell King 	 * to the TDA998x address pins.  Hence, it always has the same
19527e8675f0SRussell King 	 * offset.
19537e8675f0SRussell King 	 */
19547e8675f0SRussell King 	memset(&cec_info, 0, sizeof(cec_info));
1955f4a0659fSAzeem Shaikh 	strscpy(cec_info.type, "tda9950", sizeof(cec_info.type));
19567e8675f0SRussell King 	cec_info.addr = priv->cec_addr;
19577e8675f0SRussell King 	cec_info.platform_data = &priv->cec_glue;
19587e8675f0SRussell King 	cec_info.irq = client->irq;
19597e8675f0SRussell King 
1960bf2993c1SWolfram Sang 	priv->cec = i2c_new_client_device(client->adapter, &cec_info);
1961bf2993c1SWolfram Sang 	if (IS_ERR(priv->cec)) {
1962bf2993c1SWolfram Sang 		ret = PTR_ERR(priv->cec);
1963101e996bSRussell King 		goto fail;
1964101e996bSRussell King 	}
1965101e996bSRussell King 
1966e4782627SJean-Francois Moine 	/* enable EDID read irq: */
1967e4782627SJean-Francois Moine 	reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
1968e4782627SJean-Francois Moine 
19696c1187aaSRussell King 	if (np) {
19707e567624SJyri Sarha 		/* get the device tree parameters */
19710d44ea19SJean-Francois Moine 		ret = of_property_read_u32(np, "video-ports", &video);
19720d44ea19SJean-Francois Moine 		if (ret == 0) {
19730d44ea19SJean-Francois Moine 			priv->vip_cntrl_0 = video >> 16;
19740d44ea19SJean-Francois Moine 			priv->vip_cntrl_1 = video >> 8;
19750d44ea19SJean-Francois Moine 			priv->vip_cntrl_2 = video;
19760d44ea19SJean-Francois Moine 		}
19770d44ea19SJean-Francois Moine 
19787e567624SJyri Sarha 		ret = tda998x_get_audio_ports(priv, np);
19797e567624SJyri Sarha 		if (ret)
19807e567624SJyri Sarha 			goto fail;
19817e567624SJyri Sarha 
198271689160SRussell King 		if (priv->audio_port_enable[AUDIO_ROUTE_I2S] ||
198371689160SRussell King 		    priv->audio_port_enable[AUDIO_ROUTE_SPDIF])
19847e567624SJyri Sarha 			tda998x_audio_codec_init(priv, &client->dev);
198576767fdaSRussell King 	} else if (dev->platform_data) {
1986a03a915bSRussell King 		ret = tda998x_set_config(priv, dev->platform_data);
1987a03a915bSRussell King 		if (ret)
1988a03a915bSRussell King 			goto fail;
19896c1187aaSRussell King 	}
19907e567624SJyri Sarha 
199130bd8b86SRussell King 	priv->bridge.funcs = &tda998x_bridge_funcs;
199230bd8b86SRussell King #ifdef CONFIG_OF
199330bd8b86SRussell King 	priv->bridge.of_node = dev->of_node;
199430bd8b86SRussell King #endif
199530bd8b86SRussell King 
199630bd8b86SRussell King 	drm_bridge_add(&priv->bridge);
19977e567624SJyri Sarha 
19987e567624SJyri Sarha 	return 0;
19996a765c3fSRussell King 
2000e7792ce2SRob Clark fail:
20012143adb0SRussell King 	tda998x_destroy(dev);
20026a765c3fSRussell King err_irq:
20036a765c3fSRussell King 	return ret;
2004e7792ce2SRob Clark }
2005e7792ce2SRob Clark 
200630bd8b86SRussell King /* DRM encoder functions */
2007c707c361SRussell King 
tda998x_encoder_init(struct device * dev,struct drm_device * drm)200830bd8b86SRussell King static int tda998x_encoder_init(struct device *dev, struct drm_device *drm)
200994579273SRussell King {
201030bd8b86SRussell King 	struct tda998x_priv *priv = dev_get_drvdata(dev);
2011e66e03abSRussell King 	u32 crtcs = 0;
2012c707c361SRussell King 	int ret;
2013c707c361SRussell King 
20145dbcf319SRussell King 	if (dev->of_node)
20155dbcf319SRussell King 		crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
20165dbcf319SRussell King 
20175dbcf319SRussell King 	/* If no CRTCs were found, fall back to our old behaviour */
20185dbcf319SRussell King 	if (crtcs == 0) {
20195dbcf319SRussell King 		dev_warn(dev, "Falling back to first CRTC\n");
20205dbcf319SRussell King 		crtcs = 1 << 0;
20215dbcf319SRussell King 	}
20225dbcf319SRussell King 
2023a3584f60SRussell King 	priv->encoder.possible_crtcs = crtcs;
2024c707c361SRussell King 
2025a1170f90SThomas Zimmermann 	ret = drm_simple_encoder_init(drm, &priv->encoder,
2026a1170f90SThomas Zimmermann 				      DRM_MODE_ENCODER_TMDS);
2027c707c361SRussell King 	if (ret)
2028c707c361SRussell King 		goto err_encoder;
2029c707c361SRussell King 
2030a25b988fSLaurent Pinchart 	ret = drm_bridge_attach(&priv->encoder, &priv->bridge, NULL, 0);
2031c707c361SRussell King 	if (ret)
203230bd8b86SRussell King 		goto err_bridge;
2033c707c361SRussell King 
2034c707c361SRussell King 	return 0;
2035c707c361SRussell King 
203630bd8b86SRussell King err_bridge:
2037a3584f60SRussell King 	drm_encoder_cleanup(&priv->encoder);
2038c707c361SRussell King err_encoder:
2039c707c361SRussell King 	return ret;
2040c707c361SRussell King }
2041c707c361SRussell King 
tda998x_bind(struct device * dev,struct device * master,void * data)204230bd8b86SRussell King static int tda998x_bind(struct device *dev, struct device *master, void *data)
204330bd8b86SRussell King {
204430bd8b86SRussell King 	struct drm_device *drm = data;
204530bd8b86SRussell King 
20465a03f534SRussell King 	return tda998x_encoder_init(dev, drm);
204730bd8b86SRussell King }
2048c707c361SRussell King 
tda998x_unbind(struct device * dev,struct device * master,void * data)2049c707c361SRussell King static void tda998x_unbind(struct device *dev, struct device *master,
2050c707c361SRussell King 			   void *data)
2051c707c361SRussell King {
2052a3584f60SRussell King 	struct tda998x_priv *priv = dev_get_drvdata(dev);
2053c707c361SRussell King 
2054a3584f60SRussell King 	drm_encoder_cleanup(&priv->encoder);
2055c707c361SRussell King }
2056c707c361SRussell King 
2057c707c361SRussell King static const struct component_ops tda998x_ops = {
2058c707c361SRussell King 	.bind = tda998x_bind,
2059c707c361SRussell King 	.unbind = tda998x_unbind,
2060c707c361SRussell King };
2061c707c361SRussell King 
2062c707c361SRussell King static int
tda998x_probe(struct i2c_client * client)206330725995SUwe Kleine-König tda998x_probe(struct i2c_client *client)
2064c707c361SRussell King {
20655a03f534SRussell King 	int ret;
20665a03f534SRussell King 
206714e5b588SRussell King 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
206814e5b588SRussell King 		dev_warn(&client->dev, "adapter does not support I2C\n");
206914e5b588SRussell King 		return -EIO;
207014e5b588SRussell King 	}
20715a03f534SRussell King 
20725a03f534SRussell King 	ret = tda998x_create(&client->dev);
20735a03f534SRussell King 	if (ret)
20745a03f534SRussell King 		return ret;
20755a03f534SRussell King 
20765a03f534SRussell King 	ret = component_add(&client->dev, &tda998x_ops);
20775a03f534SRussell King 	if (ret)
20785a03f534SRussell King 		tda998x_destroy(&client->dev);
20795a03f534SRussell King 	return ret;
2080c707c361SRussell King }
2081c707c361SRussell King 
tda998x_remove(struct i2c_client * client)2082ed5c2f5fSUwe Kleine-König static void tda998x_remove(struct i2c_client *client)
2083c707c361SRussell King {
2084c707c361SRussell King 	component_del(&client->dev, &tda998x_ops);
20855a03f534SRussell King 	tda998x_destroy(&client->dev);
2086c707c361SRussell King }
2087c707c361SRussell King 
20880d44ea19SJean-Francois Moine #ifdef CONFIG_OF
20890d44ea19SJean-Francois Moine static const struct of_device_id tda998x_dt_ids[] = {
20900d44ea19SJean-Francois Moine 	{ .compatible = "nxp,tda998x", },
20910d44ea19SJean-Francois Moine 	{ }
20920d44ea19SJean-Francois Moine };
20930d44ea19SJean-Francois Moine MODULE_DEVICE_TABLE(of, tda998x_dt_ids);
20940d44ea19SJean-Francois Moine #endif
20950d44ea19SJean-Francois Moine 
2096b7f08c89SArvind Yadav static const struct i2c_device_id tda998x_ids[] = {
2097e7792ce2SRob Clark 	{ "tda998x", 0 },
2098e7792ce2SRob Clark 	{ }
2099e7792ce2SRob Clark };
2100e7792ce2SRob Clark MODULE_DEVICE_TABLE(i2c, tda998x_ids);
2101e7792ce2SRob Clark 
21023d58e318SRussell King static struct i2c_driver tda998x_driver = {
2103332af828SUwe Kleine-König 	.probe = tda998x_probe,
2104e7792ce2SRob Clark 	.remove = tda998x_remove,
2105e7792ce2SRob Clark 	.driver = {
2106e7792ce2SRob Clark 		.name = "tda998x",
21070d44ea19SJean-Francois Moine 		.of_match_table = of_match_ptr(tda998x_dt_ids),
2108e7792ce2SRob Clark 	},
2109e7792ce2SRob Clark 	.id_table = tda998x_ids,
2110e7792ce2SRob Clark };
2111e7792ce2SRob Clark 
21123d58e318SRussell King module_i2c_driver(tda998x_driver);
2113e7792ce2SRob Clark 
2114e7792ce2SRob Clark MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
2115e7792ce2SRob Clark MODULE_DESCRIPTION("NXP Semiconductors TDA998X HDMI Encoder");
2116e7792ce2SRob Clark MODULE_LICENSE("GPL");
2117