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