1325ba852SDmitry Baryshkov // SPDX-License-Identifier: GPL-2.0-only
2325ba852SDmitry Baryshkov /*
3325ba852SDmitry Baryshkov * Copyright (C) 2012 Texas Instruments
4325ba852SDmitry Baryshkov * Author: Rob Clark <robdclark@gmail.com>
5325ba852SDmitry Baryshkov */
6325ba852SDmitry Baryshkov
7325ba852SDmitry Baryshkov #include <linux/component.h>
8325ba852SDmitry Baryshkov #include <linux/gpio/consumer.h>
9325ba852SDmitry Baryshkov #include <linux/hdmi.h>
10325ba852SDmitry Baryshkov #include <linux/i2c.h>
11325ba852SDmitry Baryshkov #include <linux/module.h>
12325ba852SDmitry Baryshkov #include <linux/platform_data/tda9950.h>
13325ba852SDmitry Baryshkov #include <linux/irq.h>
14325ba852SDmitry Baryshkov #include <sound/asoundef.h>
15325ba852SDmitry Baryshkov #include <sound/hdmi-codec.h>
16325ba852SDmitry Baryshkov
17325ba852SDmitry Baryshkov #include <drm/drm_atomic_helper.h>
18325ba852SDmitry Baryshkov #include <drm/drm_bridge.h>
19325ba852SDmitry Baryshkov #include <drm/drm_edid.h>
20325ba852SDmitry Baryshkov #include <drm/drm_of.h>
21325ba852SDmitry Baryshkov #include <drm/drm_print.h>
22325ba852SDmitry Baryshkov #include <drm/drm_probe_helper.h>
23325ba852SDmitry Baryshkov #include <drm/drm_simple_kms_helper.h>
24325ba852SDmitry Baryshkov
25325ba852SDmitry Baryshkov #include <media/cec-notifier.h>
26325ba852SDmitry Baryshkov
27325ba852SDmitry Baryshkov #include <dt-bindings/display/tda998x.h>
28325ba852SDmitry Baryshkov
29325ba852SDmitry Baryshkov #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
30325ba852SDmitry Baryshkov
31325ba852SDmitry Baryshkov enum {
32325ba852SDmitry Baryshkov AUDIO_ROUTE_I2S,
33325ba852SDmitry Baryshkov AUDIO_ROUTE_SPDIF,
34325ba852SDmitry Baryshkov AUDIO_ROUTE_NUM
35325ba852SDmitry Baryshkov };
36325ba852SDmitry Baryshkov
37325ba852SDmitry Baryshkov struct tda998x_audio_route {
38325ba852SDmitry Baryshkov u8 ena_aclk;
39325ba852SDmitry Baryshkov u8 mux_ap;
40325ba852SDmitry Baryshkov u8 aip_clksel;
41325ba852SDmitry Baryshkov };
42325ba852SDmitry Baryshkov
43325ba852SDmitry Baryshkov struct tda998x_audio_settings {
44325ba852SDmitry Baryshkov const struct tda998x_audio_route *route;
45325ba852SDmitry Baryshkov struct hdmi_audio_infoframe cea;
46325ba852SDmitry Baryshkov unsigned int sample_rate;
47325ba852SDmitry Baryshkov u8 status[5];
48325ba852SDmitry Baryshkov u8 ena_ap;
49325ba852SDmitry Baryshkov u8 i2s_format;
50325ba852SDmitry Baryshkov u8 cts_n;
51325ba852SDmitry Baryshkov };
52325ba852SDmitry Baryshkov
53325ba852SDmitry Baryshkov struct tda998x_priv {
54325ba852SDmitry Baryshkov struct i2c_client *cec;
55325ba852SDmitry Baryshkov struct i2c_client *hdmi;
56325ba852SDmitry Baryshkov struct mutex mutex;
57325ba852SDmitry Baryshkov u16 rev;
58325ba852SDmitry Baryshkov u8 cec_addr;
59325ba852SDmitry Baryshkov u8 current_page;
60325ba852SDmitry Baryshkov bool is_on;
61325ba852SDmitry Baryshkov bool supports_infoframes;
62325ba852SDmitry Baryshkov bool sink_has_audio;
63325ba852SDmitry Baryshkov enum hdmi_quantization_range rgb_quant_range;
64325ba852SDmitry Baryshkov u8 vip_cntrl_0;
65325ba852SDmitry Baryshkov u8 vip_cntrl_1;
66325ba852SDmitry Baryshkov u8 vip_cntrl_2;
67325ba852SDmitry Baryshkov unsigned long tmds_clock;
68325ba852SDmitry Baryshkov struct tda998x_audio_settings audio;
69325ba852SDmitry Baryshkov
70325ba852SDmitry Baryshkov struct platform_device *audio_pdev;
71325ba852SDmitry Baryshkov struct mutex audio_mutex;
72325ba852SDmitry Baryshkov
73325ba852SDmitry Baryshkov struct mutex edid_mutex;
74325ba852SDmitry Baryshkov wait_queue_head_t wq_edid;
75325ba852SDmitry Baryshkov volatile int wq_edid_wait;
76325ba852SDmitry Baryshkov
77325ba852SDmitry Baryshkov struct work_struct detect_work;
78325ba852SDmitry Baryshkov struct timer_list edid_delay_timer;
79325ba852SDmitry Baryshkov wait_queue_head_t edid_delay_waitq;
80325ba852SDmitry Baryshkov bool edid_delay_active;
81325ba852SDmitry Baryshkov
82325ba852SDmitry Baryshkov struct drm_encoder encoder;
83325ba852SDmitry Baryshkov struct drm_bridge bridge;
84325ba852SDmitry Baryshkov struct drm_connector connector;
85325ba852SDmitry Baryshkov
86325ba852SDmitry Baryshkov u8 audio_port_enable[AUDIO_ROUTE_NUM];
87325ba852SDmitry Baryshkov struct tda9950_glue cec_glue;
88325ba852SDmitry Baryshkov struct gpio_desc *calib;
89325ba852SDmitry Baryshkov struct cec_notifier *cec_notify;
90325ba852SDmitry Baryshkov };
91325ba852SDmitry Baryshkov
92325ba852SDmitry Baryshkov #define conn_to_tda998x_priv(x) \
93325ba852SDmitry Baryshkov container_of(x, struct tda998x_priv, connector)
94325ba852SDmitry Baryshkov #define enc_to_tda998x_priv(x) \
95325ba852SDmitry Baryshkov container_of(x, struct tda998x_priv, encoder)
96325ba852SDmitry Baryshkov #define bridge_to_tda998x_priv(x) \
97325ba852SDmitry Baryshkov container_of(x, struct tda998x_priv, bridge)
98325ba852SDmitry Baryshkov
99325ba852SDmitry Baryshkov /* The TDA9988 series of devices use a paged register scheme.. to simplify
100325ba852SDmitry Baryshkov * things we encode the page # in upper bits of the register #. To read/
101325ba852SDmitry Baryshkov * write a given register, we need to make sure CURPAGE register is set
102325ba852SDmitry Baryshkov * appropriately. Which implies reads/writes are not atomic. Fun!
103325ba852SDmitry Baryshkov */
104325ba852SDmitry Baryshkov
105325ba852SDmitry Baryshkov #define REG(page, addr) (((page) << 8) | (addr))
106325ba852SDmitry Baryshkov #define REG2ADDR(reg) ((reg) & 0xff)
107325ba852SDmitry Baryshkov #define REG2PAGE(reg) (((reg) >> 8) & 0xff)
108325ba852SDmitry Baryshkov
109325ba852SDmitry Baryshkov #define REG_CURPAGE 0xff /* write */
110325ba852SDmitry Baryshkov
111325ba852SDmitry Baryshkov
112325ba852SDmitry Baryshkov /* Page 00h: General Control */
113325ba852SDmitry Baryshkov #define REG_VERSION_LSB REG(0x00, 0x00) /* read */
114325ba852SDmitry Baryshkov #define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */
115325ba852SDmitry Baryshkov # define MAIN_CNTRL0_SR (1 << 0)
116325ba852SDmitry Baryshkov # define MAIN_CNTRL0_DECS (1 << 1)
117325ba852SDmitry Baryshkov # define MAIN_CNTRL0_DEHS (1 << 2)
118325ba852SDmitry Baryshkov # define MAIN_CNTRL0_CECS (1 << 3)
119325ba852SDmitry Baryshkov # define MAIN_CNTRL0_CEHS (1 << 4)
120325ba852SDmitry Baryshkov # define MAIN_CNTRL0_SCALER (1 << 7)
121325ba852SDmitry Baryshkov #define REG_VERSION_MSB REG(0x00, 0x02) /* read */
122325ba852SDmitry Baryshkov #define REG_SOFTRESET REG(0x00, 0x0a) /* write */
123325ba852SDmitry Baryshkov # define SOFTRESET_AUDIO (1 << 0)
124325ba852SDmitry Baryshkov # define SOFTRESET_I2C_MASTER (1 << 1)
125325ba852SDmitry Baryshkov #define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */
126325ba852SDmitry Baryshkov #define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */
127325ba852SDmitry Baryshkov #define REG_I2C_MASTER REG(0x00, 0x0d) /* read/write */
128325ba852SDmitry Baryshkov # define I2C_MASTER_DIS_MM (1 << 0)
129325ba852SDmitry Baryshkov # define I2C_MASTER_DIS_FILT (1 << 1)
130325ba852SDmitry Baryshkov # define I2C_MASTER_APP_STRT_LAT (1 << 2)
131325ba852SDmitry Baryshkov #define REG_FEAT_POWERDOWN REG(0x00, 0x0e) /* read/write */
132325ba852SDmitry Baryshkov # define FEAT_POWERDOWN_PREFILT BIT(0)
133325ba852SDmitry Baryshkov # define FEAT_POWERDOWN_CSC BIT(1)
134325ba852SDmitry Baryshkov # define FEAT_POWERDOWN_SPDIF (1 << 3)
135325ba852SDmitry Baryshkov #define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */
136325ba852SDmitry Baryshkov #define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */
137325ba852SDmitry Baryshkov #define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */
138325ba852SDmitry Baryshkov # define INT_FLAGS_2_EDID_BLK_RD (1 << 1)
139325ba852SDmitry Baryshkov #define REG_ENA_ACLK REG(0x00, 0x16) /* read/write */
140325ba852SDmitry Baryshkov #define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */
141325ba852SDmitry Baryshkov #define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */
142325ba852SDmitry Baryshkov #define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */
143325ba852SDmitry Baryshkov #define REG_ENA_AP REG(0x00, 0x1e) /* read/write */
144325ba852SDmitry Baryshkov #define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */
145325ba852SDmitry Baryshkov # define VIP_CNTRL_0_MIRR_A (1 << 7)
146325ba852SDmitry Baryshkov # define VIP_CNTRL_0_SWAP_A(x) (((x) & 7) << 4)
147325ba852SDmitry Baryshkov # define VIP_CNTRL_0_MIRR_B (1 << 3)
148325ba852SDmitry Baryshkov # define VIP_CNTRL_0_SWAP_B(x) (((x) & 7) << 0)
149325ba852SDmitry Baryshkov #define REG_VIP_CNTRL_1 REG(0x00, 0x21) /* write */
150325ba852SDmitry Baryshkov # define VIP_CNTRL_1_MIRR_C (1 << 7)
151325ba852SDmitry Baryshkov # define VIP_CNTRL_1_SWAP_C(x) (((x) & 7) << 4)
152325ba852SDmitry Baryshkov # define VIP_CNTRL_1_MIRR_D (1 << 3)
153325ba852SDmitry Baryshkov # define VIP_CNTRL_1_SWAP_D(x) (((x) & 7) << 0)
154325ba852SDmitry Baryshkov #define REG_VIP_CNTRL_2 REG(0x00, 0x22) /* write */
155325ba852SDmitry Baryshkov # define VIP_CNTRL_2_MIRR_E (1 << 7)
156325ba852SDmitry Baryshkov # define VIP_CNTRL_2_SWAP_E(x) (((x) & 7) << 4)
157325ba852SDmitry Baryshkov # define VIP_CNTRL_2_MIRR_F (1 << 3)
158325ba852SDmitry Baryshkov # define VIP_CNTRL_2_SWAP_F(x) (((x) & 7) << 0)
159325ba852SDmitry Baryshkov #define REG_VIP_CNTRL_3 REG(0x00, 0x23) /* write */
160325ba852SDmitry Baryshkov # define VIP_CNTRL_3_X_TGL (1 << 0)
161325ba852SDmitry Baryshkov # define VIP_CNTRL_3_H_TGL (1 << 1)
162325ba852SDmitry Baryshkov # define VIP_CNTRL_3_V_TGL (1 << 2)
163325ba852SDmitry Baryshkov # define VIP_CNTRL_3_EMB (1 << 3)
164325ba852SDmitry Baryshkov # define VIP_CNTRL_3_SYNC_DE (1 << 4)
165325ba852SDmitry Baryshkov # define VIP_CNTRL_3_SYNC_HS (1 << 5)
166325ba852SDmitry Baryshkov # define VIP_CNTRL_3_DE_INT (1 << 6)
167325ba852SDmitry Baryshkov # define VIP_CNTRL_3_EDGE (1 << 7)
168325ba852SDmitry Baryshkov #define REG_VIP_CNTRL_4 REG(0x00, 0x24) /* write */
169325ba852SDmitry Baryshkov # define VIP_CNTRL_4_BLC(x) (((x) & 3) << 0)
170325ba852SDmitry Baryshkov # define VIP_CNTRL_4_BLANKIT(x) (((x) & 3) << 2)
171325ba852SDmitry Baryshkov # define VIP_CNTRL_4_CCIR656 (1 << 4)
172325ba852SDmitry Baryshkov # define VIP_CNTRL_4_656_ALT (1 << 5)
173325ba852SDmitry Baryshkov # define VIP_CNTRL_4_TST_656 (1 << 6)
174325ba852SDmitry Baryshkov # define VIP_CNTRL_4_TST_PAT (1 << 7)
175325ba852SDmitry Baryshkov #define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */
176325ba852SDmitry Baryshkov # define VIP_CNTRL_5_CKCASE (1 << 0)
177325ba852SDmitry Baryshkov # define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1)
178325ba852SDmitry Baryshkov #define REG_MUX_AP REG(0x00, 0x26) /* read/write */
179325ba852SDmitry Baryshkov # define MUX_AP_SELECT_I2S 0x64
180325ba852SDmitry Baryshkov # define MUX_AP_SELECT_SPDIF 0x40
181325ba852SDmitry Baryshkov #define REG_MUX_VP_VIP_OUT REG(0x00, 0x27) /* read/write */
182325ba852SDmitry Baryshkov #define REG_MAT_CONTRL REG(0x00, 0x80) /* write */
183325ba852SDmitry Baryshkov # define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0)
184325ba852SDmitry Baryshkov # define MAT_CONTRL_MAT_BP (1 << 2)
185325ba852SDmitry Baryshkov #define REG_VIDFORMAT REG(0x00, 0xa0) /* write */
186325ba852SDmitry Baryshkov #define REG_REFPIX_MSB REG(0x00, 0xa1) /* write */
187325ba852SDmitry Baryshkov #define REG_REFPIX_LSB REG(0x00, 0xa2) /* write */
188325ba852SDmitry Baryshkov #define REG_REFLINE_MSB REG(0x00, 0xa3) /* write */
189325ba852SDmitry Baryshkov #define REG_REFLINE_LSB REG(0x00, 0xa4) /* write */
190325ba852SDmitry Baryshkov #define REG_NPIX_MSB REG(0x00, 0xa5) /* write */
191325ba852SDmitry Baryshkov #define REG_NPIX_LSB REG(0x00, 0xa6) /* write */
192325ba852SDmitry Baryshkov #define REG_NLINE_MSB REG(0x00, 0xa7) /* write */
193325ba852SDmitry Baryshkov #define REG_NLINE_LSB REG(0x00, 0xa8) /* write */
194325ba852SDmitry Baryshkov #define REG_VS_LINE_STRT_1_MSB REG(0x00, 0xa9) /* write */
195325ba852SDmitry Baryshkov #define REG_VS_LINE_STRT_1_LSB REG(0x00, 0xaa) /* write */
196325ba852SDmitry Baryshkov #define REG_VS_PIX_STRT_1_MSB REG(0x00, 0xab) /* write */
197325ba852SDmitry Baryshkov #define REG_VS_PIX_STRT_1_LSB REG(0x00, 0xac) /* write */
198325ba852SDmitry Baryshkov #define REG_VS_LINE_END_1_MSB REG(0x00, 0xad) /* write */
199325ba852SDmitry Baryshkov #define REG_VS_LINE_END_1_LSB REG(0x00, 0xae) /* write */
200325ba852SDmitry Baryshkov #define REG_VS_PIX_END_1_MSB REG(0x00, 0xaf) /* write */
201325ba852SDmitry Baryshkov #define REG_VS_PIX_END_1_LSB REG(0x00, 0xb0) /* write */
202325ba852SDmitry Baryshkov #define REG_VS_LINE_STRT_2_MSB REG(0x00, 0xb1) /* write */
203325ba852SDmitry Baryshkov #define REG_VS_LINE_STRT_2_LSB REG(0x00, 0xb2) /* write */
204325ba852SDmitry Baryshkov #define REG_VS_PIX_STRT_2_MSB REG(0x00, 0xb3) /* write */
205325ba852SDmitry Baryshkov #define REG_VS_PIX_STRT_2_LSB REG(0x00, 0xb4) /* write */
206325ba852SDmitry Baryshkov #define REG_VS_LINE_END_2_MSB REG(0x00, 0xb5) /* write */
207325ba852SDmitry Baryshkov #define REG_VS_LINE_END_2_LSB REG(0x00, 0xb6) /* write */
208325ba852SDmitry Baryshkov #define REG_VS_PIX_END_2_MSB REG(0x00, 0xb7) /* write */
209325ba852SDmitry Baryshkov #define REG_VS_PIX_END_2_LSB REG(0x00, 0xb8) /* write */
210325ba852SDmitry Baryshkov #define REG_HS_PIX_START_MSB REG(0x00, 0xb9) /* write */
211325ba852SDmitry Baryshkov #define REG_HS_PIX_START_LSB REG(0x00, 0xba) /* write */
212325ba852SDmitry Baryshkov #define REG_HS_PIX_STOP_MSB REG(0x00, 0xbb) /* write */
213325ba852SDmitry Baryshkov #define REG_HS_PIX_STOP_LSB REG(0x00, 0xbc) /* write */
214325ba852SDmitry Baryshkov #define REG_VWIN_START_1_MSB REG(0x00, 0xbd) /* write */
215325ba852SDmitry Baryshkov #define REG_VWIN_START_1_LSB REG(0x00, 0xbe) /* write */
216325ba852SDmitry Baryshkov #define REG_VWIN_END_1_MSB REG(0x00, 0xbf) /* write */
217325ba852SDmitry Baryshkov #define REG_VWIN_END_1_LSB REG(0x00, 0xc0) /* write */
218325ba852SDmitry Baryshkov #define REG_VWIN_START_2_MSB REG(0x00, 0xc1) /* write */
219325ba852SDmitry Baryshkov #define REG_VWIN_START_2_LSB REG(0x00, 0xc2) /* write */
220325ba852SDmitry Baryshkov #define REG_VWIN_END_2_MSB REG(0x00, 0xc3) /* write */
221325ba852SDmitry Baryshkov #define REG_VWIN_END_2_LSB REG(0x00, 0xc4) /* write */
222325ba852SDmitry Baryshkov #define REG_DE_START_MSB REG(0x00, 0xc5) /* write */
223325ba852SDmitry Baryshkov #define REG_DE_START_LSB REG(0x00, 0xc6) /* write */
224325ba852SDmitry Baryshkov #define REG_DE_STOP_MSB REG(0x00, 0xc7) /* write */
225325ba852SDmitry Baryshkov #define REG_DE_STOP_LSB REG(0x00, 0xc8) /* write */
226325ba852SDmitry Baryshkov #define REG_TBG_CNTRL_0 REG(0x00, 0xca) /* write */
227325ba852SDmitry Baryshkov # define TBG_CNTRL_0_TOP_TGL (1 << 0)
228325ba852SDmitry Baryshkov # define TBG_CNTRL_0_TOP_SEL (1 << 1)
229325ba852SDmitry Baryshkov # define TBG_CNTRL_0_DE_EXT (1 << 2)
230325ba852SDmitry Baryshkov # define TBG_CNTRL_0_TOP_EXT (1 << 3)
231325ba852SDmitry Baryshkov # define TBG_CNTRL_0_FRAME_DIS (1 << 5)
232325ba852SDmitry Baryshkov # define TBG_CNTRL_0_SYNC_MTHD (1 << 6)
233325ba852SDmitry Baryshkov # define TBG_CNTRL_0_SYNC_ONCE (1 << 7)
234325ba852SDmitry Baryshkov #define REG_TBG_CNTRL_1 REG(0x00, 0xcb) /* write */
235325ba852SDmitry Baryshkov # define TBG_CNTRL_1_H_TGL (1 << 0)
236325ba852SDmitry Baryshkov # define TBG_CNTRL_1_V_TGL (1 << 1)
237325ba852SDmitry Baryshkov # define TBG_CNTRL_1_TGL_EN (1 << 2)
238325ba852SDmitry Baryshkov # define TBG_CNTRL_1_X_EXT (1 << 3)
239325ba852SDmitry Baryshkov # define TBG_CNTRL_1_H_EXT (1 << 4)
240325ba852SDmitry Baryshkov # define TBG_CNTRL_1_V_EXT (1 << 5)
241325ba852SDmitry Baryshkov # define TBG_CNTRL_1_DWIN_DIS (1 << 6)
242325ba852SDmitry Baryshkov #define REG_ENABLE_SPACE REG(0x00, 0xd6) /* write */
243325ba852SDmitry Baryshkov #define REG_HVF_CNTRL_0 REG(0x00, 0xe4) /* write */
244325ba852SDmitry Baryshkov # define HVF_CNTRL_0_SM (1 << 7)
245325ba852SDmitry Baryshkov # define HVF_CNTRL_0_RWB (1 << 6)
246325ba852SDmitry Baryshkov # define HVF_CNTRL_0_PREFIL(x) (((x) & 3) << 2)
247325ba852SDmitry Baryshkov # define HVF_CNTRL_0_INTPOL(x) (((x) & 3) << 0)
248325ba852SDmitry Baryshkov #define REG_HVF_CNTRL_1 REG(0x00, 0xe5) /* write */
249325ba852SDmitry Baryshkov # define HVF_CNTRL_1_FOR (1 << 0)
250325ba852SDmitry Baryshkov # define HVF_CNTRL_1_YUVBLK (1 << 1)
251325ba852SDmitry Baryshkov # define HVF_CNTRL_1_VQR(x) (((x) & 3) << 2)
252325ba852SDmitry Baryshkov # define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4)
253325ba852SDmitry Baryshkov # define HVF_CNTRL_1_SEMI_PLANAR (1 << 6)
254325ba852SDmitry Baryshkov #define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */
255325ba852SDmitry Baryshkov # define RPT_CNTRL_REPEAT(x) ((x) & 15)
256325ba852SDmitry Baryshkov #define REG_I2S_FORMAT REG(0x00, 0xfc) /* read/write */
257325ba852SDmitry Baryshkov # define I2S_FORMAT_PHILIPS (0 << 0)
258325ba852SDmitry Baryshkov # define I2S_FORMAT_LEFT_J (2 << 0)
259325ba852SDmitry Baryshkov # define I2S_FORMAT_RIGHT_J (3 << 0)
260325ba852SDmitry Baryshkov #define REG_AIP_CLKSEL REG(0x00, 0xfd) /* write */
261325ba852SDmitry Baryshkov # define AIP_CLKSEL_AIP_SPDIF (0 << 3)
262325ba852SDmitry Baryshkov # define AIP_CLKSEL_AIP_I2S (1 << 3)
263325ba852SDmitry Baryshkov # define AIP_CLKSEL_FS_ACLK (0 << 0)
264325ba852SDmitry Baryshkov # define AIP_CLKSEL_FS_MCLK (1 << 0)
265325ba852SDmitry Baryshkov # define AIP_CLKSEL_FS_FS64SPDIF (2 << 0)
266325ba852SDmitry Baryshkov
267325ba852SDmitry Baryshkov /* Page 02h: PLL settings */
268325ba852SDmitry Baryshkov #define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */
269325ba852SDmitry Baryshkov # define PLL_SERIAL_1_SRL_FDN (1 << 0)
270325ba852SDmitry Baryshkov # define PLL_SERIAL_1_SRL_IZ(x) (((x) & 3) << 1)
271325ba852SDmitry Baryshkov # define PLL_SERIAL_1_SRL_MAN_IZ (1 << 6)
272325ba852SDmitry Baryshkov #define REG_PLL_SERIAL_2 REG(0x02, 0x01) /* read/write */
273325ba852SDmitry Baryshkov # define PLL_SERIAL_2_SRL_NOSC(x) ((x) << 0)
274325ba852SDmitry Baryshkov # define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4)
275325ba852SDmitry Baryshkov #define REG_PLL_SERIAL_3 REG(0x02, 0x02) /* read/write */
276325ba852SDmitry Baryshkov # define PLL_SERIAL_3_SRL_CCIR (1 << 0)
277325ba852SDmitry Baryshkov # define PLL_SERIAL_3_SRL_DE (1 << 2)
278325ba852SDmitry Baryshkov # define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4)
279325ba852SDmitry Baryshkov #define REG_SERIALIZER REG(0x02, 0x03) /* read/write */
280325ba852SDmitry Baryshkov #define REG_BUFFER_OUT REG(0x02, 0x04) /* read/write */
281325ba852SDmitry Baryshkov #define REG_PLL_SCG1 REG(0x02, 0x05) /* read/write */
282325ba852SDmitry Baryshkov #define REG_PLL_SCG2 REG(0x02, 0x06) /* read/write */
283325ba852SDmitry Baryshkov #define REG_PLL_SCGN1 REG(0x02, 0x07) /* read/write */
284325ba852SDmitry Baryshkov #define REG_PLL_SCGN2 REG(0x02, 0x08) /* read/write */
285325ba852SDmitry Baryshkov #define REG_PLL_SCGR1 REG(0x02, 0x09) /* read/write */
286325ba852SDmitry Baryshkov #define REG_PLL_SCGR2 REG(0x02, 0x0a) /* read/write */
287325ba852SDmitry Baryshkov #define REG_AUDIO_DIV REG(0x02, 0x0e) /* read/write */
288325ba852SDmitry Baryshkov # define AUDIO_DIV_SERCLK_1 0
289325ba852SDmitry Baryshkov # define AUDIO_DIV_SERCLK_2 1
290325ba852SDmitry Baryshkov # define AUDIO_DIV_SERCLK_4 2
291325ba852SDmitry Baryshkov # define AUDIO_DIV_SERCLK_8 3
292325ba852SDmitry Baryshkov # define AUDIO_DIV_SERCLK_16 4
293325ba852SDmitry Baryshkov # define AUDIO_DIV_SERCLK_32 5
294325ba852SDmitry Baryshkov #define REG_SEL_CLK REG(0x02, 0x11) /* read/write */
295325ba852SDmitry Baryshkov # define SEL_CLK_SEL_CLK1 (1 << 0)
296325ba852SDmitry Baryshkov # define SEL_CLK_SEL_VRF_CLK(x) (((x) & 3) << 1)
297325ba852SDmitry Baryshkov # define SEL_CLK_ENA_SC_CLK (1 << 3)
298325ba852SDmitry Baryshkov #define REG_ANA_GENERAL REG(0x02, 0x12) /* read/write */
299325ba852SDmitry Baryshkov
300325ba852SDmitry Baryshkov
301325ba852SDmitry Baryshkov /* Page 09h: EDID Control */
302325ba852SDmitry Baryshkov #define REG_EDID_DATA_0 REG(0x09, 0x00) /* read */
303325ba852SDmitry Baryshkov /* next 127 successive registers are the EDID block */
304325ba852SDmitry Baryshkov #define REG_EDID_CTRL REG(0x09, 0xfa) /* read/write */
305325ba852SDmitry Baryshkov #define REG_DDC_ADDR REG(0x09, 0xfb) /* read/write */
306325ba852SDmitry Baryshkov #define REG_DDC_OFFS REG(0x09, 0xfc) /* read/write */
307325ba852SDmitry Baryshkov #define REG_DDC_SEGM_ADDR REG(0x09, 0xfd) /* read/write */
308325ba852SDmitry Baryshkov #define REG_DDC_SEGM REG(0x09, 0xfe) /* read/write */
309325ba852SDmitry Baryshkov
310325ba852SDmitry Baryshkov
311325ba852SDmitry Baryshkov /* Page 10h: information frames and packets */
312325ba852SDmitry Baryshkov #define REG_IF1_HB0 REG(0x10, 0x20) /* read/write */
313325ba852SDmitry Baryshkov #define REG_IF2_HB0 REG(0x10, 0x40) /* read/write */
314325ba852SDmitry Baryshkov #define REG_IF3_HB0 REG(0x10, 0x60) /* read/write */
315325ba852SDmitry Baryshkov #define REG_IF4_HB0 REG(0x10, 0x80) /* read/write */
316325ba852SDmitry Baryshkov #define REG_IF5_HB0 REG(0x10, 0xa0) /* read/write */
317325ba852SDmitry Baryshkov
318325ba852SDmitry Baryshkov
319325ba852SDmitry Baryshkov /* Page 11h: audio settings and content info packets */
320325ba852SDmitry Baryshkov #define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */
321325ba852SDmitry Baryshkov # define AIP_CNTRL_0_RST_FIFO (1 << 0)
322325ba852SDmitry Baryshkov # define AIP_CNTRL_0_SWAP (1 << 1)
323325ba852SDmitry Baryshkov # define AIP_CNTRL_0_LAYOUT (1 << 2)
324325ba852SDmitry Baryshkov # define AIP_CNTRL_0_ACR_MAN (1 << 5)
325325ba852SDmitry Baryshkov # define AIP_CNTRL_0_RST_CTS (1 << 6)
326325ba852SDmitry Baryshkov #define REG_CA_I2S REG(0x11, 0x01) /* read/write */
327325ba852SDmitry Baryshkov # define CA_I2S_CA_I2S(x) (((x) & 31) << 0)
328325ba852SDmitry Baryshkov # define CA_I2S_HBR_CHSTAT (1 << 6)
329325ba852SDmitry Baryshkov #define REG_LATENCY_RD REG(0x11, 0x04) /* read/write */
330325ba852SDmitry Baryshkov #define REG_ACR_CTS_0 REG(0x11, 0x05) /* read/write */
331325ba852SDmitry Baryshkov #define REG_ACR_CTS_1 REG(0x11, 0x06) /* read/write */
332325ba852SDmitry Baryshkov #define REG_ACR_CTS_2 REG(0x11, 0x07) /* read/write */
333325ba852SDmitry Baryshkov #define REG_ACR_N_0 REG(0x11, 0x08) /* read/write */
334325ba852SDmitry Baryshkov #define REG_ACR_N_1 REG(0x11, 0x09) /* read/write */
335325ba852SDmitry Baryshkov #define REG_ACR_N_2 REG(0x11, 0x0a) /* read/write */
336325ba852SDmitry Baryshkov #define REG_CTS_N REG(0x11, 0x0c) /* read/write */
337325ba852SDmitry Baryshkov # define CTS_N_K(x) (((x) & 7) << 0)
338325ba852SDmitry Baryshkov # define CTS_N_M(x) (((x) & 3) << 4)
339325ba852SDmitry Baryshkov #define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */
340325ba852SDmitry Baryshkov # define ENC_CNTRL_RST_ENC (1 << 0)
341325ba852SDmitry Baryshkov # define ENC_CNTRL_RST_SEL (1 << 1)
342325ba852SDmitry Baryshkov # define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2)
343325ba852SDmitry Baryshkov #define REG_DIP_FLAGS REG(0x11, 0x0e) /* read/write */
344325ba852SDmitry Baryshkov # define DIP_FLAGS_ACR (1 << 0)
345325ba852SDmitry Baryshkov # define DIP_FLAGS_GC (1 << 1)
346325ba852SDmitry Baryshkov #define REG_DIP_IF_FLAGS REG(0x11, 0x0f) /* read/write */
347325ba852SDmitry Baryshkov # define DIP_IF_FLAGS_IF1 (1 << 1)
348325ba852SDmitry Baryshkov # define DIP_IF_FLAGS_IF2 (1 << 2)
349325ba852SDmitry Baryshkov # define DIP_IF_FLAGS_IF3 (1 << 3)
350325ba852SDmitry Baryshkov # define DIP_IF_FLAGS_IF4 (1 << 4)
351325ba852SDmitry Baryshkov # define DIP_IF_FLAGS_IF5 (1 << 5)
352325ba852SDmitry Baryshkov #define REG_CH_STAT_B(x) REG(0x11, 0x14 + (x)) /* read/write */
353325ba852SDmitry Baryshkov
354325ba852SDmitry Baryshkov
355325ba852SDmitry Baryshkov /* Page 12h: HDCP and OTP */
356325ba852SDmitry Baryshkov #define REG_TX3 REG(0x12, 0x9a) /* read/write */
357325ba852SDmitry Baryshkov #define REG_TX4 REG(0x12, 0x9b) /* read/write */
358325ba852SDmitry Baryshkov # define TX4_PD_RAM (1 << 1)
359325ba852SDmitry Baryshkov #define REG_TX33 REG(0x12, 0xb8) /* read/write */
360325ba852SDmitry Baryshkov # define TX33_HDMI (1 << 1)
361325ba852SDmitry Baryshkov
362325ba852SDmitry Baryshkov
363325ba852SDmitry Baryshkov /* Page 13h: Gamut related metadata packets */
364325ba852SDmitry Baryshkov
365325ba852SDmitry Baryshkov
366325ba852SDmitry Baryshkov
367325ba852SDmitry Baryshkov /* CEC registers: (not paged)
368325ba852SDmitry Baryshkov */
369325ba852SDmitry Baryshkov #define REG_CEC_INTSTATUS 0xee /* read */
370325ba852SDmitry Baryshkov # define CEC_INTSTATUS_CEC (1 << 0)
371325ba852SDmitry Baryshkov # define CEC_INTSTATUS_HDMI (1 << 1)
372325ba852SDmitry Baryshkov #define REG_CEC_CAL_XOSC_CTRL1 0xf2
373325ba852SDmitry Baryshkov # define CEC_CAL_XOSC_CTRL1_ENA_CAL BIT(0)
374325ba852SDmitry Baryshkov #define REG_CEC_DES_FREQ2 0xf5
375325ba852SDmitry Baryshkov # define CEC_DES_FREQ2_DIS_AUTOCAL BIT(7)
376325ba852SDmitry Baryshkov #define REG_CEC_CLK 0xf6
377325ba852SDmitry Baryshkov # define CEC_CLK_FRO 0x11
378325ba852SDmitry Baryshkov #define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */
379325ba852SDmitry Baryshkov # define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7)
380325ba852SDmitry Baryshkov # define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6)
381325ba852SDmitry Baryshkov # define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1)
382325ba852SDmitry Baryshkov # define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0)
383325ba852SDmitry Baryshkov #define REG_CEC_RXSHPDINTENA 0xfc /* read/write */
384325ba852SDmitry Baryshkov #define REG_CEC_RXSHPDINT 0xfd /* read */
385325ba852SDmitry Baryshkov # define CEC_RXSHPDINT_RXSENS BIT(0)
386325ba852SDmitry Baryshkov # define CEC_RXSHPDINT_HPD BIT(1)
387325ba852SDmitry Baryshkov #define REG_CEC_RXSHPDLEV 0xfe /* read */
388325ba852SDmitry Baryshkov # define CEC_RXSHPDLEV_RXSENS (1 << 0)
389325ba852SDmitry Baryshkov # define CEC_RXSHPDLEV_HPD (1 << 1)
390325ba852SDmitry Baryshkov
391325ba852SDmitry Baryshkov #define REG_CEC_ENAMODS 0xff /* read/write */
392325ba852SDmitry Baryshkov # define CEC_ENAMODS_EN_CEC_CLK (1 << 7)
393325ba852SDmitry Baryshkov # define CEC_ENAMODS_DIS_FRO (1 << 6)
394325ba852SDmitry Baryshkov # define CEC_ENAMODS_DIS_CCLK (1 << 5)
395325ba852SDmitry Baryshkov # define CEC_ENAMODS_EN_RXSENS (1 << 2)
396325ba852SDmitry Baryshkov # define CEC_ENAMODS_EN_HDMI (1 << 1)
397325ba852SDmitry Baryshkov # define CEC_ENAMODS_EN_CEC (1 << 0)
398325ba852SDmitry Baryshkov
399325ba852SDmitry Baryshkov
400325ba852SDmitry Baryshkov /* Device versions: */
401325ba852SDmitry Baryshkov #define TDA9989N2 0x0101
402325ba852SDmitry Baryshkov #define TDA19989 0x0201
403325ba852SDmitry Baryshkov #define TDA19989N2 0x0202
404325ba852SDmitry Baryshkov #define TDA19988 0x0301
405325ba852SDmitry Baryshkov
406325ba852SDmitry Baryshkov static void
cec_write(struct tda998x_priv * priv,u16 addr,u8 val)407325ba852SDmitry Baryshkov cec_write(struct tda998x_priv *priv, u16 addr, u8 val)
408325ba852SDmitry Baryshkov {
409325ba852SDmitry Baryshkov u8 buf[] = {addr, val};
410325ba852SDmitry Baryshkov struct i2c_msg msg = {
411325ba852SDmitry Baryshkov .addr = priv->cec_addr,
412325ba852SDmitry Baryshkov .len = 2,
413325ba852SDmitry Baryshkov .buf = buf,
414325ba852SDmitry Baryshkov };
415325ba852SDmitry Baryshkov int ret;
416325ba852SDmitry Baryshkov
417325ba852SDmitry Baryshkov ret = i2c_transfer(priv->hdmi->adapter, &msg, 1);
418325ba852SDmitry Baryshkov if (ret < 0)
419325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev, "Error %d writing to cec:0x%x\n",
420325ba852SDmitry Baryshkov ret, addr);
421325ba852SDmitry Baryshkov }
422325ba852SDmitry Baryshkov
423325ba852SDmitry Baryshkov static u8
cec_read(struct tda998x_priv * priv,u8 addr)424325ba852SDmitry Baryshkov cec_read(struct tda998x_priv *priv, u8 addr)
425325ba852SDmitry Baryshkov {
426325ba852SDmitry Baryshkov u8 val;
427325ba852SDmitry Baryshkov struct i2c_msg msg[2] = {
428325ba852SDmitry Baryshkov {
429325ba852SDmitry Baryshkov .addr = priv->cec_addr,
430325ba852SDmitry Baryshkov .len = 1,
431325ba852SDmitry Baryshkov .buf = &addr,
432325ba852SDmitry Baryshkov }, {
433325ba852SDmitry Baryshkov .addr = priv->cec_addr,
434325ba852SDmitry Baryshkov .flags = I2C_M_RD,
435325ba852SDmitry Baryshkov .len = 1,
436325ba852SDmitry Baryshkov .buf = &val,
437325ba852SDmitry Baryshkov },
438325ba852SDmitry Baryshkov };
439325ba852SDmitry Baryshkov int ret;
440325ba852SDmitry Baryshkov
441325ba852SDmitry Baryshkov ret = i2c_transfer(priv->hdmi->adapter, msg, ARRAY_SIZE(msg));
442325ba852SDmitry Baryshkov if (ret < 0) {
443325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev, "Error %d reading from cec:0x%x\n",
444325ba852SDmitry Baryshkov ret, addr);
445325ba852SDmitry Baryshkov val = 0;
446325ba852SDmitry Baryshkov }
447325ba852SDmitry Baryshkov
448325ba852SDmitry Baryshkov return val;
449325ba852SDmitry Baryshkov }
450325ba852SDmitry Baryshkov
cec_enamods(struct tda998x_priv * priv,u8 mods,bool enable)451325ba852SDmitry Baryshkov static void cec_enamods(struct tda998x_priv *priv, u8 mods, bool enable)
452325ba852SDmitry Baryshkov {
453325ba852SDmitry Baryshkov int val = cec_read(priv, REG_CEC_ENAMODS);
454325ba852SDmitry Baryshkov
455325ba852SDmitry Baryshkov if (val < 0)
456325ba852SDmitry Baryshkov return;
457325ba852SDmitry Baryshkov
458325ba852SDmitry Baryshkov if (enable)
459325ba852SDmitry Baryshkov val |= mods;
460325ba852SDmitry Baryshkov else
461325ba852SDmitry Baryshkov val &= ~mods;
462325ba852SDmitry Baryshkov
463325ba852SDmitry Baryshkov cec_write(priv, REG_CEC_ENAMODS, val);
464325ba852SDmitry Baryshkov }
465325ba852SDmitry Baryshkov
tda998x_cec_set_calibration(struct tda998x_priv * priv,bool enable)466325ba852SDmitry Baryshkov static void tda998x_cec_set_calibration(struct tda998x_priv *priv, bool enable)
467325ba852SDmitry Baryshkov {
468325ba852SDmitry Baryshkov if (enable) {
469325ba852SDmitry Baryshkov u8 val;
470325ba852SDmitry Baryshkov
471325ba852SDmitry Baryshkov cec_write(priv, 0xf3, 0xc0);
472325ba852SDmitry Baryshkov cec_write(priv, 0xf4, 0xd4);
473325ba852SDmitry Baryshkov
474325ba852SDmitry Baryshkov /* Enable automatic calibration mode */
475325ba852SDmitry Baryshkov val = cec_read(priv, REG_CEC_DES_FREQ2);
476325ba852SDmitry Baryshkov val &= ~CEC_DES_FREQ2_DIS_AUTOCAL;
477325ba852SDmitry Baryshkov cec_write(priv, REG_CEC_DES_FREQ2, val);
478325ba852SDmitry Baryshkov
479325ba852SDmitry Baryshkov /* Enable free running oscillator */
480325ba852SDmitry Baryshkov cec_write(priv, REG_CEC_CLK, CEC_CLK_FRO);
481325ba852SDmitry Baryshkov cec_enamods(priv, CEC_ENAMODS_DIS_FRO, false);
482325ba852SDmitry Baryshkov
483325ba852SDmitry Baryshkov cec_write(priv, REG_CEC_CAL_XOSC_CTRL1,
484325ba852SDmitry Baryshkov CEC_CAL_XOSC_CTRL1_ENA_CAL);
485325ba852SDmitry Baryshkov } else {
486325ba852SDmitry Baryshkov cec_write(priv, REG_CEC_CAL_XOSC_CTRL1, 0);
487325ba852SDmitry Baryshkov }
488325ba852SDmitry Baryshkov }
489325ba852SDmitry Baryshkov
490325ba852SDmitry Baryshkov /*
491325ba852SDmitry Baryshkov * Calibration for the internal oscillator: we need to set calibration mode,
492325ba852SDmitry Baryshkov * and then pulse the IRQ line low for a 10ms ± 1% period.
493325ba852SDmitry Baryshkov */
tda998x_cec_calibration(struct tda998x_priv * priv)494325ba852SDmitry Baryshkov static void tda998x_cec_calibration(struct tda998x_priv *priv)
495325ba852SDmitry Baryshkov {
496325ba852SDmitry Baryshkov struct gpio_desc *calib = priv->calib;
497325ba852SDmitry Baryshkov
498325ba852SDmitry Baryshkov mutex_lock(&priv->edid_mutex);
499325ba852SDmitry Baryshkov if (priv->hdmi->irq > 0)
500325ba852SDmitry Baryshkov disable_irq(priv->hdmi->irq);
501325ba852SDmitry Baryshkov gpiod_direction_output(calib, 1);
502325ba852SDmitry Baryshkov tda998x_cec_set_calibration(priv, true);
503325ba852SDmitry Baryshkov
504325ba852SDmitry Baryshkov local_irq_disable();
505325ba852SDmitry Baryshkov gpiod_set_value(calib, 0);
506325ba852SDmitry Baryshkov mdelay(10);
507325ba852SDmitry Baryshkov gpiod_set_value(calib, 1);
508325ba852SDmitry Baryshkov local_irq_enable();
509325ba852SDmitry Baryshkov
510325ba852SDmitry Baryshkov tda998x_cec_set_calibration(priv, false);
511325ba852SDmitry Baryshkov gpiod_direction_input(calib);
512325ba852SDmitry Baryshkov if (priv->hdmi->irq > 0)
513325ba852SDmitry Baryshkov enable_irq(priv->hdmi->irq);
514325ba852SDmitry Baryshkov mutex_unlock(&priv->edid_mutex);
515325ba852SDmitry Baryshkov }
516325ba852SDmitry Baryshkov
tda998x_cec_hook_init(void * data)517325ba852SDmitry Baryshkov static int tda998x_cec_hook_init(void *data)
518325ba852SDmitry Baryshkov {
519325ba852SDmitry Baryshkov struct tda998x_priv *priv = data;
520325ba852SDmitry Baryshkov struct gpio_desc *calib;
521325ba852SDmitry Baryshkov
522325ba852SDmitry Baryshkov calib = gpiod_get(&priv->hdmi->dev, "nxp,calib", GPIOD_ASIS);
523325ba852SDmitry Baryshkov if (IS_ERR(calib)) {
524325ba852SDmitry Baryshkov dev_warn(&priv->hdmi->dev, "failed to get calibration gpio: %ld\n",
525325ba852SDmitry Baryshkov PTR_ERR(calib));
526325ba852SDmitry Baryshkov return PTR_ERR(calib);
527325ba852SDmitry Baryshkov }
528325ba852SDmitry Baryshkov
529325ba852SDmitry Baryshkov priv->calib = calib;
530325ba852SDmitry Baryshkov
531325ba852SDmitry Baryshkov return 0;
532325ba852SDmitry Baryshkov }
533325ba852SDmitry Baryshkov
tda998x_cec_hook_exit(void * data)534325ba852SDmitry Baryshkov static void tda998x_cec_hook_exit(void *data)
535325ba852SDmitry Baryshkov {
536325ba852SDmitry Baryshkov struct tda998x_priv *priv = data;
537325ba852SDmitry Baryshkov
538325ba852SDmitry Baryshkov gpiod_put(priv->calib);
539325ba852SDmitry Baryshkov priv->calib = NULL;
540325ba852SDmitry Baryshkov }
541325ba852SDmitry Baryshkov
tda998x_cec_hook_open(void * data)542325ba852SDmitry Baryshkov static int tda998x_cec_hook_open(void *data)
543325ba852SDmitry Baryshkov {
544325ba852SDmitry Baryshkov struct tda998x_priv *priv = data;
545325ba852SDmitry Baryshkov
546325ba852SDmitry Baryshkov cec_enamods(priv, CEC_ENAMODS_EN_CEC_CLK | CEC_ENAMODS_EN_CEC, true);
547325ba852SDmitry Baryshkov tda998x_cec_calibration(priv);
548325ba852SDmitry Baryshkov
549325ba852SDmitry Baryshkov return 0;
550325ba852SDmitry Baryshkov }
551325ba852SDmitry Baryshkov
tda998x_cec_hook_release(void * data)552325ba852SDmitry Baryshkov static void tda998x_cec_hook_release(void *data)
553325ba852SDmitry Baryshkov {
554325ba852SDmitry Baryshkov struct tda998x_priv *priv = data;
555325ba852SDmitry Baryshkov
556325ba852SDmitry Baryshkov cec_enamods(priv, CEC_ENAMODS_EN_CEC_CLK | CEC_ENAMODS_EN_CEC, false);
557325ba852SDmitry Baryshkov }
558325ba852SDmitry Baryshkov
559325ba852SDmitry Baryshkov static int
set_page(struct tda998x_priv * priv,u16 reg)560325ba852SDmitry Baryshkov set_page(struct tda998x_priv *priv, u16 reg)
561325ba852SDmitry Baryshkov {
562325ba852SDmitry Baryshkov if (REG2PAGE(reg) != priv->current_page) {
563325ba852SDmitry Baryshkov struct i2c_client *client = priv->hdmi;
564325ba852SDmitry Baryshkov u8 buf[] = {
565325ba852SDmitry Baryshkov REG_CURPAGE, REG2PAGE(reg)
566325ba852SDmitry Baryshkov };
567325ba852SDmitry Baryshkov int ret = i2c_master_send(client, buf, sizeof(buf));
568325ba852SDmitry Baryshkov if (ret < 0) {
569325ba852SDmitry Baryshkov dev_err(&client->dev, "%s %04x err %d\n", __func__,
570325ba852SDmitry Baryshkov reg, ret);
571325ba852SDmitry Baryshkov return ret;
572325ba852SDmitry Baryshkov }
573325ba852SDmitry Baryshkov
574325ba852SDmitry Baryshkov priv->current_page = REG2PAGE(reg);
575325ba852SDmitry Baryshkov }
576325ba852SDmitry Baryshkov return 0;
577325ba852SDmitry Baryshkov }
578325ba852SDmitry Baryshkov
579325ba852SDmitry Baryshkov static int
reg_read_range(struct tda998x_priv * priv,u16 reg,char * buf,int cnt)580325ba852SDmitry Baryshkov reg_read_range(struct tda998x_priv *priv, u16 reg, char *buf, int cnt)
581325ba852SDmitry Baryshkov {
582325ba852SDmitry Baryshkov struct i2c_client *client = priv->hdmi;
583325ba852SDmitry Baryshkov u8 addr = REG2ADDR(reg);
584325ba852SDmitry Baryshkov int ret;
585325ba852SDmitry Baryshkov
586325ba852SDmitry Baryshkov mutex_lock(&priv->mutex);
587325ba852SDmitry Baryshkov ret = set_page(priv, reg);
588325ba852SDmitry Baryshkov if (ret < 0)
589325ba852SDmitry Baryshkov goto out;
590325ba852SDmitry Baryshkov
591325ba852SDmitry Baryshkov ret = i2c_master_send(client, &addr, sizeof(addr));
592325ba852SDmitry Baryshkov if (ret < 0)
593325ba852SDmitry Baryshkov goto fail;
594325ba852SDmitry Baryshkov
595325ba852SDmitry Baryshkov ret = i2c_master_recv(client, buf, cnt);
596325ba852SDmitry Baryshkov if (ret < 0)
597325ba852SDmitry Baryshkov goto fail;
598325ba852SDmitry Baryshkov
599325ba852SDmitry Baryshkov goto out;
600325ba852SDmitry Baryshkov
601325ba852SDmitry Baryshkov fail:
602325ba852SDmitry Baryshkov dev_err(&client->dev, "Error %d reading from 0x%x\n", ret, reg);
603325ba852SDmitry Baryshkov out:
604325ba852SDmitry Baryshkov mutex_unlock(&priv->mutex);
605325ba852SDmitry Baryshkov return ret;
606325ba852SDmitry Baryshkov }
607325ba852SDmitry Baryshkov
608325ba852SDmitry Baryshkov #define MAX_WRITE_RANGE_BUF 32
609325ba852SDmitry Baryshkov
610325ba852SDmitry Baryshkov static void
reg_write_range(struct tda998x_priv * priv,u16 reg,u8 * p,int cnt)611325ba852SDmitry Baryshkov reg_write_range(struct tda998x_priv *priv, u16 reg, u8 *p, int cnt)
612325ba852SDmitry Baryshkov {
613325ba852SDmitry Baryshkov struct i2c_client *client = priv->hdmi;
614325ba852SDmitry Baryshkov /* This is the maximum size of the buffer passed in */
615325ba852SDmitry Baryshkov u8 buf[MAX_WRITE_RANGE_BUF + 1];
616325ba852SDmitry Baryshkov int ret;
617325ba852SDmitry Baryshkov
618325ba852SDmitry Baryshkov if (cnt > MAX_WRITE_RANGE_BUF) {
619325ba852SDmitry Baryshkov dev_err(&client->dev, "Fixed write buffer too small (%d)\n",
620325ba852SDmitry Baryshkov MAX_WRITE_RANGE_BUF);
621325ba852SDmitry Baryshkov return;
622325ba852SDmitry Baryshkov }
623325ba852SDmitry Baryshkov
624325ba852SDmitry Baryshkov buf[0] = REG2ADDR(reg);
625325ba852SDmitry Baryshkov memcpy(&buf[1], p, cnt);
626325ba852SDmitry Baryshkov
627325ba852SDmitry Baryshkov mutex_lock(&priv->mutex);
628325ba852SDmitry Baryshkov ret = set_page(priv, reg);
629325ba852SDmitry Baryshkov if (ret < 0)
630325ba852SDmitry Baryshkov goto out;
631325ba852SDmitry Baryshkov
632325ba852SDmitry Baryshkov ret = i2c_master_send(client, buf, cnt + 1);
633325ba852SDmitry Baryshkov if (ret < 0)
634325ba852SDmitry Baryshkov dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
635325ba852SDmitry Baryshkov out:
636325ba852SDmitry Baryshkov mutex_unlock(&priv->mutex);
637325ba852SDmitry Baryshkov }
638325ba852SDmitry Baryshkov
639325ba852SDmitry Baryshkov static int
reg_read(struct tda998x_priv * priv,u16 reg)640325ba852SDmitry Baryshkov reg_read(struct tda998x_priv *priv, u16 reg)
641325ba852SDmitry Baryshkov {
642325ba852SDmitry Baryshkov u8 val = 0;
643325ba852SDmitry Baryshkov int ret;
644325ba852SDmitry Baryshkov
645325ba852SDmitry Baryshkov ret = reg_read_range(priv, reg, &val, sizeof(val));
646325ba852SDmitry Baryshkov if (ret < 0)
647325ba852SDmitry Baryshkov return ret;
648325ba852SDmitry Baryshkov return val;
649325ba852SDmitry Baryshkov }
650325ba852SDmitry Baryshkov
651325ba852SDmitry Baryshkov static void
reg_write(struct tda998x_priv * priv,u16 reg,u8 val)652325ba852SDmitry Baryshkov reg_write(struct tda998x_priv *priv, u16 reg, u8 val)
653325ba852SDmitry Baryshkov {
654325ba852SDmitry Baryshkov struct i2c_client *client = priv->hdmi;
655325ba852SDmitry Baryshkov u8 buf[] = {REG2ADDR(reg), val};
656325ba852SDmitry Baryshkov int ret;
657325ba852SDmitry Baryshkov
658325ba852SDmitry Baryshkov mutex_lock(&priv->mutex);
659325ba852SDmitry Baryshkov ret = set_page(priv, reg);
660325ba852SDmitry Baryshkov if (ret < 0)
661325ba852SDmitry Baryshkov goto out;
662325ba852SDmitry Baryshkov
663325ba852SDmitry Baryshkov ret = i2c_master_send(client, buf, sizeof(buf));
664325ba852SDmitry Baryshkov if (ret < 0)
665325ba852SDmitry Baryshkov dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
666325ba852SDmitry Baryshkov out:
667325ba852SDmitry Baryshkov mutex_unlock(&priv->mutex);
668325ba852SDmitry Baryshkov }
669325ba852SDmitry Baryshkov
670325ba852SDmitry Baryshkov static void
reg_write16(struct tda998x_priv * priv,u16 reg,u16 val)671325ba852SDmitry Baryshkov reg_write16(struct tda998x_priv *priv, u16 reg, u16 val)
672325ba852SDmitry Baryshkov {
673325ba852SDmitry Baryshkov struct i2c_client *client = priv->hdmi;
674325ba852SDmitry Baryshkov u8 buf[] = {REG2ADDR(reg), val >> 8, val};
675325ba852SDmitry Baryshkov int ret;
676325ba852SDmitry Baryshkov
677325ba852SDmitry Baryshkov mutex_lock(&priv->mutex);
678325ba852SDmitry Baryshkov ret = set_page(priv, reg);
679325ba852SDmitry Baryshkov if (ret < 0)
680325ba852SDmitry Baryshkov goto out;
681325ba852SDmitry Baryshkov
682325ba852SDmitry Baryshkov ret = i2c_master_send(client, buf, sizeof(buf));
683325ba852SDmitry Baryshkov if (ret < 0)
684325ba852SDmitry Baryshkov dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
685325ba852SDmitry Baryshkov out:
686325ba852SDmitry Baryshkov mutex_unlock(&priv->mutex);
687325ba852SDmitry Baryshkov }
688325ba852SDmitry Baryshkov
689325ba852SDmitry Baryshkov static void
reg_set(struct tda998x_priv * priv,u16 reg,u8 val)690325ba852SDmitry Baryshkov reg_set(struct tda998x_priv *priv, u16 reg, u8 val)
691325ba852SDmitry Baryshkov {
692325ba852SDmitry Baryshkov int old_val;
693325ba852SDmitry Baryshkov
694325ba852SDmitry Baryshkov old_val = reg_read(priv, reg);
695325ba852SDmitry Baryshkov if (old_val >= 0)
696325ba852SDmitry Baryshkov reg_write(priv, reg, old_val | val);
697325ba852SDmitry Baryshkov }
698325ba852SDmitry Baryshkov
699325ba852SDmitry Baryshkov static void
reg_clear(struct tda998x_priv * priv,u16 reg,u8 val)700325ba852SDmitry Baryshkov reg_clear(struct tda998x_priv *priv, u16 reg, u8 val)
701325ba852SDmitry Baryshkov {
702325ba852SDmitry Baryshkov int old_val;
703325ba852SDmitry Baryshkov
704325ba852SDmitry Baryshkov old_val = reg_read(priv, reg);
705325ba852SDmitry Baryshkov if (old_val >= 0)
706325ba852SDmitry Baryshkov reg_write(priv, reg, old_val & ~val);
707325ba852SDmitry Baryshkov }
708325ba852SDmitry Baryshkov
709325ba852SDmitry Baryshkov static void
tda998x_reset(struct tda998x_priv * priv)710325ba852SDmitry Baryshkov tda998x_reset(struct tda998x_priv *priv)
711325ba852SDmitry Baryshkov {
712325ba852SDmitry Baryshkov /* reset audio and i2c master: */
713325ba852SDmitry Baryshkov reg_write(priv, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
714325ba852SDmitry Baryshkov msleep(50);
715325ba852SDmitry Baryshkov reg_write(priv, REG_SOFTRESET, 0);
716325ba852SDmitry Baryshkov msleep(50);
717325ba852SDmitry Baryshkov
718325ba852SDmitry Baryshkov /* reset transmitter: */
719325ba852SDmitry Baryshkov reg_set(priv, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
720325ba852SDmitry Baryshkov reg_clear(priv, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
721325ba852SDmitry Baryshkov
722325ba852SDmitry Baryshkov /* PLL registers common configuration */
723325ba852SDmitry Baryshkov reg_write(priv, REG_PLL_SERIAL_1, 0x00);
724325ba852SDmitry Baryshkov reg_write(priv, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1));
725325ba852SDmitry Baryshkov reg_write(priv, REG_PLL_SERIAL_3, 0x00);
726325ba852SDmitry Baryshkov reg_write(priv, REG_SERIALIZER, 0x00);
727325ba852SDmitry Baryshkov reg_write(priv, REG_BUFFER_OUT, 0x00);
728325ba852SDmitry Baryshkov reg_write(priv, REG_PLL_SCG1, 0x00);
729325ba852SDmitry Baryshkov reg_write(priv, REG_AUDIO_DIV, AUDIO_DIV_SERCLK_8);
730325ba852SDmitry Baryshkov reg_write(priv, REG_SEL_CLK, SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
731325ba852SDmitry Baryshkov reg_write(priv, REG_PLL_SCGN1, 0xfa);
732325ba852SDmitry Baryshkov reg_write(priv, REG_PLL_SCGN2, 0x00);
733325ba852SDmitry Baryshkov reg_write(priv, REG_PLL_SCGR1, 0x5b);
734325ba852SDmitry Baryshkov reg_write(priv, REG_PLL_SCGR2, 0x00);
735325ba852SDmitry Baryshkov reg_write(priv, REG_PLL_SCG2, 0x10);
736325ba852SDmitry Baryshkov
737325ba852SDmitry Baryshkov /* Write the default value MUX register */
738325ba852SDmitry Baryshkov reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24);
739325ba852SDmitry Baryshkov }
740325ba852SDmitry Baryshkov
741325ba852SDmitry Baryshkov /*
742325ba852SDmitry Baryshkov * The TDA998x has a problem when trying to read the EDID close to a
743325ba852SDmitry Baryshkov * HPD assertion: it needs a delay of 100ms to avoid timing out while
744325ba852SDmitry Baryshkov * trying to read EDID data.
745325ba852SDmitry Baryshkov *
746325ba852SDmitry Baryshkov * However, tda998x_connector_get_modes() may be called at any moment
747325ba852SDmitry Baryshkov * after tda998x_connector_detect() indicates that we are connected, so
748325ba852SDmitry Baryshkov * we need to delay probing modes in tda998x_connector_get_modes() after
749325ba852SDmitry Baryshkov * we have seen a HPD inactive->active transition. This code implements
750325ba852SDmitry Baryshkov * that delay.
751325ba852SDmitry Baryshkov */
tda998x_edid_delay_done(struct timer_list * t)752325ba852SDmitry Baryshkov static void tda998x_edid_delay_done(struct timer_list *t)
753325ba852SDmitry Baryshkov {
754*41cb0855SIngo Molnar struct tda998x_priv *priv = timer_container_of(priv, t,
755*41cb0855SIngo Molnar edid_delay_timer);
756325ba852SDmitry Baryshkov
757325ba852SDmitry Baryshkov priv->edid_delay_active = false;
758325ba852SDmitry Baryshkov wake_up(&priv->edid_delay_waitq);
759325ba852SDmitry Baryshkov schedule_work(&priv->detect_work);
760325ba852SDmitry Baryshkov }
761325ba852SDmitry Baryshkov
tda998x_edid_delay_start(struct tda998x_priv * priv)762325ba852SDmitry Baryshkov static void tda998x_edid_delay_start(struct tda998x_priv *priv)
763325ba852SDmitry Baryshkov {
764325ba852SDmitry Baryshkov priv->edid_delay_active = true;
765325ba852SDmitry Baryshkov mod_timer(&priv->edid_delay_timer, jiffies + HZ/10);
766325ba852SDmitry Baryshkov }
767325ba852SDmitry Baryshkov
tda998x_edid_delay_wait(struct tda998x_priv * priv)768325ba852SDmitry Baryshkov static int tda998x_edid_delay_wait(struct tda998x_priv *priv)
769325ba852SDmitry Baryshkov {
770325ba852SDmitry Baryshkov return wait_event_killable(priv->edid_delay_waitq, !priv->edid_delay_active);
771325ba852SDmitry Baryshkov }
772325ba852SDmitry Baryshkov
773325ba852SDmitry Baryshkov /*
774325ba852SDmitry Baryshkov * We need to run the KMS hotplug event helper outside of our threaded
775325ba852SDmitry Baryshkov * interrupt routine as this can call back into our get_modes method,
776325ba852SDmitry Baryshkov * which will want to make use of interrupts.
777325ba852SDmitry Baryshkov */
tda998x_detect_work(struct work_struct * work)778325ba852SDmitry Baryshkov static void tda998x_detect_work(struct work_struct *work)
779325ba852SDmitry Baryshkov {
780325ba852SDmitry Baryshkov struct tda998x_priv *priv =
781325ba852SDmitry Baryshkov container_of(work, struct tda998x_priv, detect_work);
782325ba852SDmitry Baryshkov struct drm_device *dev = priv->connector.dev;
783325ba852SDmitry Baryshkov
784325ba852SDmitry Baryshkov if (dev)
785325ba852SDmitry Baryshkov drm_kms_helper_hotplug_event(dev);
786325ba852SDmitry Baryshkov }
787325ba852SDmitry Baryshkov
788325ba852SDmitry Baryshkov /*
789325ba852SDmitry Baryshkov * only 2 interrupts may occur: screen plug/unplug and EDID read
790325ba852SDmitry Baryshkov */
tda998x_irq_thread(int irq,void * data)791325ba852SDmitry Baryshkov static irqreturn_t tda998x_irq_thread(int irq, void *data)
792325ba852SDmitry Baryshkov {
793325ba852SDmitry Baryshkov struct tda998x_priv *priv = data;
794325ba852SDmitry Baryshkov u8 sta, cec, lvl, flag0, flag1, flag2;
795325ba852SDmitry Baryshkov bool handled = false;
796325ba852SDmitry Baryshkov
797325ba852SDmitry Baryshkov sta = cec_read(priv, REG_CEC_INTSTATUS);
798325ba852SDmitry Baryshkov if (sta & CEC_INTSTATUS_HDMI) {
799325ba852SDmitry Baryshkov cec = cec_read(priv, REG_CEC_RXSHPDINT);
800325ba852SDmitry Baryshkov lvl = cec_read(priv, REG_CEC_RXSHPDLEV);
801325ba852SDmitry Baryshkov flag0 = reg_read(priv, REG_INT_FLAGS_0);
802325ba852SDmitry Baryshkov flag1 = reg_read(priv, REG_INT_FLAGS_1);
803325ba852SDmitry Baryshkov flag2 = reg_read(priv, REG_INT_FLAGS_2);
804325ba852SDmitry Baryshkov DRM_DEBUG_DRIVER(
805325ba852SDmitry Baryshkov "tda irq sta %02x cec %02x lvl %02x f0 %02x f1 %02x f2 %02x\n",
806325ba852SDmitry Baryshkov sta, cec, lvl, flag0, flag1, flag2);
807325ba852SDmitry Baryshkov
808325ba852SDmitry Baryshkov if (cec & CEC_RXSHPDINT_HPD) {
809325ba852SDmitry Baryshkov if (lvl & CEC_RXSHPDLEV_HPD) {
810325ba852SDmitry Baryshkov tda998x_edid_delay_start(priv);
811325ba852SDmitry Baryshkov } else {
812325ba852SDmitry Baryshkov schedule_work(&priv->detect_work);
813325ba852SDmitry Baryshkov cec_notifier_phys_addr_invalidate(
814325ba852SDmitry Baryshkov priv->cec_notify);
815325ba852SDmitry Baryshkov }
816325ba852SDmitry Baryshkov
817325ba852SDmitry Baryshkov handled = true;
818325ba852SDmitry Baryshkov }
819325ba852SDmitry Baryshkov
820325ba852SDmitry Baryshkov if ((flag2 & INT_FLAGS_2_EDID_BLK_RD) && priv->wq_edid_wait) {
821325ba852SDmitry Baryshkov priv->wq_edid_wait = 0;
822325ba852SDmitry Baryshkov wake_up(&priv->wq_edid);
823325ba852SDmitry Baryshkov handled = true;
824325ba852SDmitry Baryshkov }
825325ba852SDmitry Baryshkov }
826325ba852SDmitry Baryshkov
827325ba852SDmitry Baryshkov return IRQ_RETVAL(handled);
828325ba852SDmitry Baryshkov }
829325ba852SDmitry Baryshkov
830325ba852SDmitry Baryshkov static void
tda998x_write_if(struct tda998x_priv * priv,u8 bit,u16 addr,union hdmi_infoframe * frame)831325ba852SDmitry Baryshkov tda998x_write_if(struct tda998x_priv *priv, u8 bit, u16 addr,
832325ba852SDmitry Baryshkov union hdmi_infoframe *frame)
833325ba852SDmitry Baryshkov {
834325ba852SDmitry Baryshkov u8 buf[MAX_WRITE_RANGE_BUF];
835325ba852SDmitry Baryshkov ssize_t len;
836325ba852SDmitry Baryshkov
837325ba852SDmitry Baryshkov len = hdmi_infoframe_pack(frame, buf, sizeof(buf));
838325ba852SDmitry Baryshkov if (len < 0) {
839325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev,
840325ba852SDmitry Baryshkov "hdmi_infoframe_pack() type=0x%02x failed: %zd\n",
841325ba852SDmitry Baryshkov frame->any.type, len);
842325ba852SDmitry Baryshkov return;
843325ba852SDmitry Baryshkov }
844325ba852SDmitry Baryshkov
845325ba852SDmitry Baryshkov reg_clear(priv, REG_DIP_IF_FLAGS, bit);
846325ba852SDmitry Baryshkov reg_write_range(priv, addr, buf, len);
847325ba852SDmitry Baryshkov reg_set(priv, REG_DIP_IF_FLAGS, bit);
848325ba852SDmitry Baryshkov }
849325ba852SDmitry Baryshkov
tda998x_write_aif(struct tda998x_priv * priv,const struct hdmi_audio_infoframe * cea)850325ba852SDmitry Baryshkov static void tda998x_write_aif(struct tda998x_priv *priv,
851325ba852SDmitry Baryshkov const struct hdmi_audio_infoframe *cea)
852325ba852SDmitry Baryshkov {
853325ba852SDmitry Baryshkov union hdmi_infoframe frame;
854325ba852SDmitry Baryshkov
855325ba852SDmitry Baryshkov frame.audio = *cea;
856325ba852SDmitry Baryshkov
857325ba852SDmitry Baryshkov tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, &frame);
858325ba852SDmitry Baryshkov }
859325ba852SDmitry Baryshkov
860325ba852SDmitry Baryshkov static void
tda998x_write_avi(struct tda998x_priv * priv,const struct drm_display_mode * mode)861325ba852SDmitry Baryshkov tda998x_write_avi(struct tda998x_priv *priv, const struct drm_display_mode *mode)
862325ba852SDmitry Baryshkov {
863325ba852SDmitry Baryshkov union hdmi_infoframe frame;
864325ba852SDmitry Baryshkov
865325ba852SDmitry Baryshkov drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
866325ba852SDmitry Baryshkov &priv->connector, mode);
867325ba852SDmitry Baryshkov frame.avi.quantization_range = HDMI_QUANTIZATION_RANGE_FULL;
868325ba852SDmitry Baryshkov drm_hdmi_avi_infoframe_quant_range(&frame.avi, &priv->connector, mode,
869325ba852SDmitry Baryshkov priv->rgb_quant_range);
870325ba852SDmitry Baryshkov
871325ba852SDmitry Baryshkov tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, &frame);
872325ba852SDmitry Baryshkov }
873325ba852SDmitry Baryshkov
tda998x_write_vsi(struct tda998x_priv * priv,const struct drm_display_mode * mode)874325ba852SDmitry Baryshkov static void tda998x_write_vsi(struct tda998x_priv *priv,
875325ba852SDmitry Baryshkov const struct drm_display_mode *mode)
876325ba852SDmitry Baryshkov {
877325ba852SDmitry Baryshkov union hdmi_infoframe frame;
878325ba852SDmitry Baryshkov
879325ba852SDmitry Baryshkov if (drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
880325ba852SDmitry Baryshkov &priv->connector,
881325ba852SDmitry Baryshkov mode))
882325ba852SDmitry Baryshkov reg_clear(priv, REG_DIP_IF_FLAGS, DIP_IF_FLAGS_IF1);
883325ba852SDmitry Baryshkov else
884325ba852SDmitry Baryshkov tda998x_write_if(priv, DIP_IF_FLAGS_IF1, REG_IF1_HB0, &frame);
885325ba852SDmitry Baryshkov }
886325ba852SDmitry Baryshkov
887325ba852SDmitry Baryshkov /* Audio support */
888325ba852SDmitry Baryshkov
889325ba852SDmitry Baryshkov static const struct tda998x_audio_route tda998x_audio_route[AUDIO_ROUTE_NUM] = {
890325ba852SDmitry Baryshkov [AUDIO_ROUTE_I2S] = {
891325ba852SDmitry Baryshkov .ena_aclk = 1,
892325ba852SDmitry Baryshkov .mux_ap = MUX_AP_SELECT_I2S,
893325ba852SDmitry Baryshkov .aip_clksel = AIP_CLKSEL_AIP_I2S | AIP_CLKSEL_FS_ACLK,
894325ba852SDmitry Baryshkov },
895325ba852SDmitry Baryshkov [AUDIO_ROUTE_SPDIF] = {
896325ba852SDmitry Baryshkov .ena_aclk = 0,
897325ba852SDmitry Baryshkov .mux_ap = MUX_AP_SELECT_SPDIF,
898325ba852SDmitry Baryshkov .aip_clksel = AIP_CLKSEL_AIP_SPDIF | AIP_CLKSEL_FS_FS64SPDIF,
899325ba852SDmitry Baryshkov },
900325ba852SDmitry Baryshkov };
901325ba852SDmitry Baryshkov
902325ba852SDmitry Baryshkov /* Configure the TDA998x audio data and clock routing. */
tda998x_derive_routing(struct tda998x_priv * priv,struct tda998x_audio_settings * s,unsigned int route)903325ba852SDmitry Baryshkov static int tda998x_derive_routing(struct tda998x_priv *priv,
904325ba852SDmitry Baryshkov struct tda998x_audio_settings *s,
905325ba852SDmitry Baryshkov unsigned int route)
906325ba852SDmitry Baryshkov {
907325ba852SDmitry Baryshkov s->route = &tda998x_audio_route[route];
908325ba852SDmitry Baryshkov s->ena_ap = priv->audio_port_enable[route];
909325ba852SDmitry Baryshkov if (s->ena_ap == 0) {
910325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev, "no audio configuration found\n");
911325ba852SDmitry Baryshkov return -EINVAL;
912325ba852SDmitry Baryshkov }
913325ba852SDmitry Baryshkov
914325ba852SDmitry Baryshkov return 0;
915325ba852SDmitry Baryshkov }
916325ba852SDmitry Baryshkov
917325ba852SDmitry Baryshkov /*
918325ba852SDmitry Baryshkov * The audio clock divisor register controls a divider producing Audio_Clk_Out
919325ba852SDmitry Baryshkov * from SERclk by dividing it by 2^n where 0 <= n <= 5. We don't know what
920325ba852SDmitry Baryshkov * Audio_Clk_Out or SERclk are. We guess SERclk is the same as TMDS clock.
921325ba852SDmitry Baryshkov *
922325ba852SDmitry Baryshkov * It seems that Audio_Clk_Out must be the smallest value that is greater
923325ba852SDmitry Baryshkov * than 128*fs, otherwise audio does not function. There is some suggestion
924325ba852SDmitry Baryshkov * that 126*fs is a better value.
925325ba852SDmitry Baryshkov */
tda998x_get_adiv(struct tda998x_priv * priv,unsigned int fs)926325ba852SDmitry Baryshkov static u8 tda998x_get_adiv(struct tda998x_priv *priv, unsigned int fs)
927325ba852SDmitry Baryshkov {
928325ba852SDmitry Baryshkov unsigned long min_audio_clk = fs * 128;
929325ba852SDmitry Baryshkov unsigned long ser_clk = priv->tmds_clock * 1000;
930325ba852SDmitry Baryshkov u8 adiv;
931325ba852SDmitry Baryshkov
932325ba852SDmitry Baryshkov for (adiv = AUDIO_DIV_SERCLK_32; adiv != AUDIO_DIV_SERCLK_1; adiv--)
933325ba852SDmitry Baryshkov if (ser_clk > min_audio_clk << adiv)
934325ba852SDmitry Baryshkov break;
935325ba852SDmitry Baryshkov
936325ba852SDmitry Baryshkov dev_dbg(&priv->hdmi->dev,
937325ba852SDmitry Baryshkov "ser_clk=%luHz fs=%uHz min_aclk=%luHz adiv=%d\n",
938325ba852SDmitry Baryshkov ser_clk, fs, min_audio_clk, adiv);
939325ba852SDmitry Baryshkov
940325ba852SDmitry Baryshkov return adiv;
941325ba852SDmitry Baryshkov }
942325ba852SDmitry Baryshkov
943325ba852SDmitry Baryshkov /*
944325ba852SDmitry Baryshkov * In auto-CTS mode, the TDA998x uses a "measured time stamp" counter to
945325ba852SDmitry Baryshkov * generate the CTS value. It appears that the "measured time stamp" is
946325ba852SDmitry Baryshkov * the number of TDMS clock cycles within a number of audio input clock
947325ba852SDmitry Baryshkov * cycles defined by the k and N parameters defined below, in a similar
948325ba852SDmitry Baryshkov * way to that which is set out in the CTS generation in the HDMI spec.
949325ba852SDmitry Baryshkov *
950325ba852SDmitry Baryshkov * tmdsclk ----> mts -> /m ---> CTS
951325ba852SDmitry Baryshkov * ^
952325ba852SDmitry Baryshkov * sclk -> /k -> /N
953325ba852SDmitry Baryshkov *
954325ba852SDmitry Baryshkov * CTS = mts / m, where m is 2^M.
955325ba852SDmitry Baryshkov * /k is a divider based on the K value below, K+1 for K < 4, or 8 for K >= 4
956325ba852SDmitry Baryshkov * /N is a divider based on the HDMI specified N value.
957325ba852SDmitry Baryshkov *
958325ba852SDmitry Baryshkov * This produces the following equation:
959325ba852SDmitry Baryshkov * CTS = tmds_clock * k * N / (sclk * m)
960325ba852SDmitry Baryshkov *
961325ba852SDmitry Baryshkov * When combined with the sink-side equation, and realising that sclk is
962325ba852SDmitry Baryshkov * bclk_ratio * fs, we end up with:
963325ba852SDmitry Baryshkov * k = m * bclk_ratio / 128.
964325ba852SDmitry Baryshkov *
965325ba852SDmitry Baryshkov * Note: S/PDIF always uses a bclk_ratio of 64.
966325ba852SDmitry Baryshkov */
tda998x_derive_cts_n(struct tda998x_priv * priv,struct tda998x_audio_settings * settings,unsigned int ratio)967325ba852SDmitry Baryshkov static int tda998x_derive_cts_n(struct tda998x_priv *priv,
968325ba852SDmitry Baryshkov struct tda998x_audio_settings *settings,
969325ba852SDmitry Baryshkov unsigned int ratio)
970325ba852SDmitry Baryshkov {
971325ba852SDmitry Baryshkov switch (ratio) {
972325ba852SDmitry Baryshkov case 16:
973325ba852SDmitry Baryshkov settings->cts_n = CTS_N_M(3) | CTS_N_K(0);
974325ba852SDmitry Baryshkov break;
975325ba852SDmitry Baryshkov case 32:
976325ba852SDmitry Baryshkov settings->cts_n = CTS_N_M(3) | CTS_N_K(1);
977325ba852SDmitry Baryshkov break;
978325ba852SDmitry Baryshkov case 48:
979325ba852SDmitry Baryshkov settings->cts_n = CTS_N_M(3) | CTS_N_K(2);
980325ba852SDmitry Baryshkov break;
981325ba852SDmitry Baryshkov case 64:
982325ba852SDmitry Baryshkov settings->cts_n = CTS_N_M(3) | CTS_N_K(3);
983325ba852SDmitry Baryshkov break;
984325ba852SDmitry Baryshkov case 128:
985325ba852SDmitry Baryshkov settings->cts_n = CTS_N_M(0) | CTS_N_K(0);
986325ba852SDmitry Baryshkov break;
987325ba852SDmitry Baryshkov default:
988325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev, "unsupported bclk ratio %ufs\n",
989325ba852SDmitry Baryshkov ratio);
990325ba852SDmitry Baryshkov return -EINVAL;
991325ba852SDmitry Baryshkov }
992325ba852SDmitry Baryshkov return 0;
993325ba852SDmitry Baryshkov }
994325ba852SDmitry Baryshkov
tda998x_audio_mute(struct tda998x_priv * priv,bool on)995325ba852SDmitry Baryshkov static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
996325ba852SDmitry Baryshkov {
997325ba852SDmitry Baryshkov if (on) {
998325ba852SDmitry Baryshkov reg_set(priv, REG_SOFTRESET, SOFTRESET_AUDIO);
999325ba852SDmitry Baryshkov reg_clear(priv, REG_SOFTRESET, SOFTRESET_AUDIO);
1000325ba852SDmitry Baryshkov reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
1001325ba852SDmitry Baryshkov } else {
1002325ba852SDmitry Baryshkov reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
1003325ba852SDmitry Baryshkov }
1004325ba852SDmitry Baryshkov }
1005325ba852SDmitry Baryshkov
tda998x_configure_audio(struct tda998x_priv * priv)1006325ba852SDmitry Baryshkov static void tda998x_configure_audio(struct tda998x_priv *priv)
1007325ba852SDmitry Baryshkov {
1008325ba852SDmitry Baryshkov const struct tda998x_audio_settings *settings = &priv->audio;
1009325ba852SDmitry Baryshkov u8 buf[6], adiv;
1010325ba852SDmitry Baryshkov u32 n;
1011325ba852SDmitry Baryshkov
1012325ba852SDmitry Baryshkov /* If audio is not configured, there is nothing to do. */
1013325ba852SDmitry Baryshkov if (settings->ena_ap == 0)
1014325ba852SDmitry Baryshkov return;
1015325ba852SDmitry Baryshkov
1016325ba852SDmitry Baryshkov adiv = tda998x_get_adiv(priv, settings->sample_rate);
1017325ba852SDmitry Baryshkov
1018325ba852SDmitry Baryshkov /* Enable audio ports */
1019325ba852SDmitry Baryshkov reg_write(priv, REG_ENA_AP, settings->ena_ap);
1020325ba852SDmitry Baryshkov reg_write(priv, REG_ENA_ACLK, settings->route->ena_aclk);
1021325ba852SDmitry Baryshkov reg_write(priv, REG_MUX_AP, settings->route->mux_ap);
1022325ba852SDmitry Baryshkov reg_write(priv, REG_I2S_FORMAT, settings->i2s_format);
1023325ba852SDmitry Baryshkov reg_write(priv, REG_AIP_CLKSEL, settings->route->aip_clksel);
1024325ba852SDmitry Baryshkov reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT |
1025325ba852SDmitry Baryshkov AIP_CNTRL_0_ACR_MAN); /* auto CTS */
1026325ba852SDmitry Baryshkov reg_write(priv, REG_CTS_N, settings->cts_n);
1027325ba852SDmitry Baryshkov reg_write(priv, REG_AUDIO_DIV, adiv);
1028325ba852SDmitry Baryshkov
1029325ba852SDmitry Baryshkov /*
1030325ba852SDmitry Baryshkov * This is the approximate value of N, which happens to be
1031325ba852SDmitry Baryshkov * the recommended values for non-coherent clocks.
1032325ba852SDmitry Baryshkov */
1033325ba852SDmitry Baryshkov n = 128 * settings->sample_rate / 1000;
1034325ba852SDmitry Baryshkov
1035325ba852SDmitry Baryshkov /* Write the CTS and N values */
1036325ba852SDmitry Baryshkov buf[0] = 0x44;
1037325ba852SDmitry Baryshkov buf[1] = 0x42;
1038325ba852SDmitry Baryshkov buf[2] = 0x01;
1039325ba852SDmitry Baryshkov buf[3] = n;
1040325ba852SDmitry Baryshkov buf[4] = n >> 8;
1041325ba852SDmitry Baryshkov buf[5] = n >> 16;
1042325ba852SDmitry Baryshkov reg_write_range(priv, REG_ACR_CTS_0, buf, 6);
1043325ba852SDmitry Baryshkov
1044325ba852SDmitry Baryshkov /* Reset CTS generator */
1045325ba852SDmitry Baryshkov reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
1046325ba852SDmitry Baryshkov reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
1047325ba852SDmitry Baryshkov
1048325ba852SDmitry Baryshkov /* Write the channel status
1049325ba852SDmitry Baryshkov * The REG_CH_STAT_B-registers skip IEC958 AES2 byte, because
1050325ba852SDmitry Baryshkov * there is a separate register for each I2S wire.
1051325ba852SDmitry Baryshkov */
1052325ba852SDmitry Baryshkov buf[0] = settings->status[0];
1053325ba852SDmitry Baryshkov buf[1] = settings->status[1];
1054325ba852SDmitry Baryshkov buf[2] = settings->status[3];
1055325ba852SDmitry Baryshkov buf[3] = settings->status[4];
1056325ba852SDmitry Baryshkov reg_write_range(priv, REG_CH_STAT_B(0), buf, 4);
1057325ba852SDmitry Baryshkov
1058325ba852SDmitry Baryshkov tda998x_audio_mute(priv, true);
1059325ba852SDmitry Baryshkov msleep(20);
1060325ba852SDmitry Baryshkov tda998x_audio_mute(priv, false);
1061325ba852SDmitry Baryshkov
1062325ba852SDmitry Baryshkov tda998x_write_aif(priv, &settings->cea);
1063325ba852SDmitry Baryshkov }
1064325ba852SDmitry Baryshkov
tda998x_audio_hw_params(struct device * dev,void * data,struct hdmi_codec_daifmt * daifmt,struct hdmi_codec_params * params)1065325ba852SDmitry Baryshkov static int tda998x_audio_hw_params(struct device *dev, void *data,
1066325ba852SDmitry Baryshkov struct hdmi_codec_daifmt *daifmt,
1067325ba852SDmitry Baryshkov struct hdmi_codec_params *params)
1068325ba852SDmitry Baryshkov {
1069325ba852SDmitry Baryshkov struct tda998x_priv *priv = dev_get_drvdata(dev);
1070325ba852SDmitry Baryshkov unsigned int bclk_ratio;
1071325ba852SDmitry Baryshkov bool spdif = daifmt->fmt == HDMI_SPDIF;
1072325ba852SDmitry Baryshkov int ret;
1073325ba852SDmitry Baryshkov struct tda998x_audio_settings audio = {
1074325ba852SDmitry Baryshkov .sample_rate = params->sample_rate,
1075325ba852SDmitry Baryshkov .cea = params->cea,
1076325ba852SDmitry Baryshkov };
1077325ba852SDmitry Baryshkov
1078325ba852SDmitry Baryshkov memcpy(audio.status, params->iec.status,
1079325ba852SDmitry Baryshkov min(sizeof(audio.status), sizeof(params->iec.status)));
1080325ba852SDmitry Baryshkov
1081325ba852SDmitry Baryshkov switch (daifmt->fmt) {
1082325ba852SDmitry Baryshkov case HDMI_I2S:
1083325ba852SDmitry Baryshkov audio.i2s_format = I2S_FORMAT_PHILIPS;
1084325ba852SDmitry Baryshkov break;
1085325ba852SDmitry Baryshkov case HDMI_LEFT_J:
1086325ba852SDmitry Baryshkov audio.i2s_format = I2S_FORMAT_LEFT_J;
1087325ba852SDmitry Baryshkov break;
1088325ba852SDmitry Baryshkov case HDMI_RIGHT_J:
1089325ba852SDmitry Baryshkov audio.i2s_format = I2S_FORMAT_RIGHT_J;
1090325ba852SDmitry Baryshkov break;
1091325ba852SDmitry Baryshkov case HDMI_SPDIF:
1092325ba852SDmitry Baryshkov audio.i2s_format = 0;
1093325ba852SDmitry Baryshkov break;
1094325ba852SDmitry Baryshkov default:
1095325ba852SDmitry Baryshkov dev_err(dev, "%s: Invalid format %d\n", __func__, daifmt->fmt);
1096325ba852SDmitry Baryshkov return -EINVAL;
1097325ba852SDmitry Baryshkov }
1098325ba852SDmitry Baryshkov
1099325ba852SDmitry Baryshkov if (!spdif &&
1100325ba852SDmitry Baryshkov (daifmt->bit_clk_inv || daifmt->frame_clk_inv ||
1101325ba852SDmitry Baryshkov daifmt->bit_clk_provider || daifmt->frame_clk_provider)) {
1102325ba852SDmitry Baryshkov dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__,
1103325ba852SDmitry Baryshkov daifmt->bit_clk_inv, daifmt->frame_clk_inv,
1104325ba852SDmitry Baryshkov daifmt->bit_clk_provider,
1105325ba852SDmitry Baryshkov daifmt->frame_clk_provider);
1106325ba852SDmitry Baryshkov return -EINVAL;
1107325ba852SDmitry Baryshkov }
1108325ba852SDmitry Baryshkov
1109325ba852SDmitry Baryshkov ret = tda998x_derive_routing(priv, &audio, AUDIO_ROUTE_I2S + spdif);
1110325ba852SDmitry Baryshkov if (ret < 0)
1111325ba852SDmitry Baryshkov return ret;
1112325ba852SDmitry Baryshkov
1113325ba852SDmitry Baryshkov bclk_ratio = spdif ? 64 : params->sample_width * 2;
1114325ba852SDmitry Baryshkov ret = tda998x_derive_cts_n(priv, &audio, bclk_ratio);
1115325ba852SDmitry Baryshkov if (ret < 0)
1116325ba852SDmitry Baryshkov return ret;
1117325ba852SDmitry Baryshkov
1118325ba852SDmitry Baryshkov mutex_lock(&priv->audio_mutex);
1119325ba852SDmitry Baryshkov priv->audio = audio;
1120325ba852SDmitry Baryshkov if (priv->supports_infoframes && priv->sink_has_audio)
1121325ba852SDmitry Baryshkov tda998x_configure_audio(priv);
1122325ba852SDmitry Baryshkov mutex_unlock(&priv->audio_mutex);
1123325ba852SDmitry Baryshkov
1124325ba852SDmitry Baryshkov return 0;
1125325ba852SDmitry Baryshkov }
1126325ba852SDmitry Baryshkov
tda998x_audio_shutdown(struct device * dev,void * data)1127325ba852SDmitry Baryshkov static void tda998x_audio_shutdown(struct device *dev, void *data)
1128325ba852SDmitry Baryshkov {
1129325ba852SDmitry Baryshkov struct tda998x_priv *priv = dev_get_drvdata(dev);
1130325ba852SDmitry Baryshkov
1131325ba852SDmitry Baryshkov mutex_lock(&priv->audio_mutex);
1132325ba852SDmitry Baryshkov
1133325ba852SDmitry Baryshkov reg_write(priv, REG_ENA_AP, 0);
1134325ba852SDmitry Baryshkov priv->audio.ena_ap = 0;
1135325ba852SDmitry Baryshkov
1136325ba852SDmitry Baryshkov mutex_unlock(&priv->audio_mutex);
1137325ba852SDmitry Baryshkov }
1138325ba852SDmitry Baryshkov
tda998x_audio_mute_stream(struct device * dev,void * data,bool enable,int direction)1139325ba852SDmitry Baryshkov static int tda998x_audio_mute_stream(struct device *dev, void *data,
1140325ba852SDmitry Baryshkov bool enable, int direction)
1141325ba852SDmitry Baryshkov {
1142325ba852SDmitry Baryshkov struct tda998x_priv *priv = dev_get_drvdata(dev);
1143325ba852SDmitry Baryshkov
1144325ba852SDmitry Baryshkov mutex_lock(&priv->audio_mutex);
1145325ba852SDmitry Baryshkov
1146325ba852SDmitry Baryshkov tda998x_audio_mute(priv, enable);
1147325ba852SDmitry Baryshkov
1148325ba852SDmitry Baryshkov mutex_unlock(&priv->audio_mutex);
1149325ba852SDmitry Baryshkov return 0;
1150325ba852SDmitry Baryshkov }
1151325ba852SDmitry Baryshkov
tda998x_audio_get_eld(struct device * dev,void * data,uint8_t * buf,size_t len)1152325ba852SDmitry Baryshkov static int tda998x_audio_get_eld(struct device *dev, void *data,
1153325ba852SDmitry Baryshkov uint8_t *buf, size_t len)
1154325ba852SDmitry Baryshkov {
1155325ba852SDmitry Baryshkov struct tda998x_priv *priv = dev_get_drvdata(dev);
1156325ba852SDmitry Baryshkov
1157325ba852SDmitry Baryshkov mutex_lock(&priv->audio_mutex);
1158325ba852SDmitry Baryshkov memcpy(buf, priv->connector.eld,
1159325ba852SDmitry Baryshkov min(sizeof(priv->connector.eld), len));
1160325ba852SDmitry Baryshkov mutex_unlock(&priv->audio_mutex);
1161325ba852SDmitry Baryshkov
1162325ba852SDmitry Baryshkov return 0;
1163325ba852SDmitry Baryshkov }
1164325ba852SDmitry Baryshkov
1165325ba852SDmitry Baryshkov static const struct hdmi_codec_ops audio_codec_ops = {
1166325ba852SDmitry Baryshkov .hw_params = tda998x_audio_hw_params,
1167325ba852SDmitry Baryshkov .audio_shutdown = tda998x_audio_shutdown,
1168325ba852SDmitry Baryshkov .mute_stream = tda998x_audio_mute_stream,
1169325ba852SDmitry Baryshkov .get_eld = tda998x_audio_get_eld,
1170325ba852SDmitry Baryshkov };
1171325ba852SDmitry Baryshkov
tda998x_audio_codec_init(struct tda998x_priv * priv,struct device * dev)1172325ba852SDmitry Baryshkov static int tda998x_audio_codec_init(struct tda998x_priv *priv,
1173325ba852SDmitry Baryshkov struct device *dev)
1174325ba852SDmitry Baryshkov {
1175325ba852SDmitry Baryshkov struct hdmi_codec_pdata codec_data = {
1176325ba852SDmitry Baryshkov .ops = &audio_codec_ops,
1177325ba852SDmitry Baryshkov .max_i2s_channels = 2,
1178325ba852SDmitry Baryshkov .no_i2s_capture = 1,
1179325ba852SDmitry Baryshkov .no_spdif_capture = 1,
1180325ba852SDmitry Baryshkov .no_capture_mute = 1,
1181325ba852SDmitry Baryshkov };
1182325ba852SDmitry Baryshkov
1183325ba852SDmitry Baryshkov if (priv->audio_port_enable[AUDIO_ROUTE_I2S])
1184325ba852SDmitry Baryshkov codec_data.i2s = 1;
1185325ba852SDmitry Baryshkov if (priv->audio_port_enable[AUDIO_ROUTE_SPDIF])
1186325ba852SDmitry Baryshkov codec_data.spdif = 1;
1187325ba852SDmitry Baryshkov
1188325ba852SDmitry Baryshkov priv->audio_pdev = platform_device_register_data(
1189325ba852SDmitry Baryshkov dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
1190325ba852SDmitry Baryshkov &codec_data, sizeof(codec_data));
1191325ba852SDmitry Baryshkov
1192325ba852SDmitry Baryshkov return PTR_ERR_OR_ZERO(priv->audio_pdev);
1193325ba852SDmitry Baryshkov }
1194325ba852SDmitry Baryshkov
1195325ba852SDmitry Baryshkov /* DRM connector functions */
1196325ba852SDmitry Baryshkov
1197325ba852SDmitry Baryshkov static enum drm_connector_status
tda998x_connector_detect(struct drm_connector * connector,bool force)1198325ba852SDmitry Baryshkov tda998x_connector_detect(struct drm_connector *connector, bool force)
1199325ba852SDmitry Baryshkov {
1200325ba852SDmitry Baryshkov struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
1201325ba852SDmitry Baryshkov u8 val = cec_read(priv, REG_CEC_RXSHPDLEV);
1202325ba852SDmitry Baryshkov
1203325ba852SDmitry Baryshkov return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
1204325ba852SDmitry Baryshkov connector_status_disconnected;
1205325ba852SDmitry Baryshkov }
1206325ba852SDmitry Baryshkov
tda998x_connector_destroy(struct drm_connector * connector)1207325ba852SDmitry Baryshkov static void tda998x_connector_destroy(struct drm_connector *connector)
1208325ba852SDmitry Baryshkov {
1209325ba852SDmitry Baryshkov drm_connector_cleanup(connector);
1210325ba852SDmitry Baryshkov }
1211325ba852SDmitry Baryshkov
1212325ba852SDmitry Baryshkov static const struct drm_connector_funcs tda998x_connector_funcs = {
1213325ba852SDmitry Baryshkov .reset = drm_atomic_helper_connector_reset,
1214325ba852SDmitry Baryshkov .fill_modes = drm_helper_probe_single_connector_modes,
1215325ba852SDmitry Baryshkov .detect = tda998x_connector_detect,
1216325ba852SDmitry Baryshkov .destroy = tda998x_connector_destroy,
1217325ba852SDmitry Baryshkov .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1218325ba852SDmitry Baryshkov .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1219325ba852SDmitry Baryshkov };
1220325ba852SDmitry Baryshkov
read_edid_block(void * data,u8 * buf,unsigned int blk,size_t length)1221325ba852SDmitry Baryshkov static int read_edid_block(void *data, u8 *buf, unsigned int blk, size_t length)
1222325ba852SDmitry Baryshkov {
1223325ba852SDmitry Baryshkov struct tda998x_priv *priv = data;
1224325ba852SDmitry Baryshkov u8 offset, segptr;
1225325ba852SDmitry Baryshkov int ret, i;
1226325ba852SDmitry Baryshkov
1227325ba852SDmitry Baryshkov offset = (blk & 1) ? 128 : 0;
1228325ba852SDmitry Baryshkov segptr = blk / 2;
1229325ba852SDmitry Baryshkov
1230325ba852SDmitry Baryshkov mutex_lock(&priv->edid_mutex);
1231325ba852SDmitry Baryshkov
1232325ba852SDmitry Baryshkov reg_write(priv, REG_DDC_ADDR, 0xa0);
1233325ba852SDmitry Baryshkov reg_write(priv, REG_DDC_OFFS, offset);
1234325ba852SDmitry Baryshkov reg_write(priv, REG_DDC_SEGM_ADDR, 0x60);
1235325ba852SDmitry Baryshkov reg_write(priv, REG_DDC_SEGM, segptr);
1236325ba852SDmitry Baryshkov
1237325ba852SDmitry Baryshkov /* enable reading EDID: */
1238325ba852SDmitry Baryshkov priv->wq_edid_wait = 1;
1239325ba852SDmitry Baryshkov reg_write(priv, REG_EDID_CTRL, 0x1);
1240325ba852SDmitry Baryshkov
1241325ba852SDmitry Baryshkov /* flag must be cleared by sw: */
1242325ba852SDmitry Baryshkov reg_write(priv, REG_EDID_CTRL, 0x0);
1243325ba852SDmitry Baryshkov
1244325ba852SDmitry Baryshkov /* wait for block read to complete: */
1245325ba852SDmitry Baryshkov if (priv->hdmi->irq) {
1246325ba852SDmitry Baryshkov i = wait_event_timeout(priv->wq_edid,
1247325ba852SDmitry Baryshkov !priv->wq_edid_wait,
1248325ba852SDmitry Baryshkov msecs_to_jiffies(100));
1249325ba852SDmitry Baryshkov if (i < 0) {
1250325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev, "read edid wait err %d\n", i);
1251325ba852SDmitry Baryshkov ret = i;
1252325ba852SDmitry Baryshkov goto failed;
1253325ba852SDmitry Baryshkov }
1254325ba852SDmitry Baryshkov } else {
1255325ba852SDmitry Baryshkov for (i = 100; i > 0; i--) {
1256325ba852SDmitry Baryshkov msleep(1);
1257325ba852SDmitry Baryshkov ret = reg_read(priv, REG_INT_FLAGS_2);
1258325ba852SDmitry Baryshkov if (ret < 0)
1259325ba852SDmitry Baryshkov goto failed;
1260325ba852SDmitry Baryshkov if (ret & INT_FLAGS_2_EDID_BLK_RD)
1261325ba852SDmitry Baryshkov break;
1262325ba852SDmitry Baryshkov }
1263325ba852SDmitry Baryshkov }
1264325ba852SDmitry Baryshkov
1265325ba852SDmitry Baryshkov if (i == 0) {
1266325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev, "read edid timeout\n");
1267325ba852SDmitry Baryshkov ret = -ETIMEDOUT;
1268325ba852SDmitry Baryshkov goto failed;
1269325ba852SDmitry Baryshkov }
1270325ba852SDmitry Baryshkov
1271325ba852SDmitry Baryshkov ret = reg_read_range(priv, REG_EDID_DATA_0, buf, length);
1272325ba852SDmitry Baryshkov if (ret != length) {
1273325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev, "failed to read edid block %d: %d\n",
1274325ba852SDmitry Baryshkov blk, ret);
1275325ba852SDmitry Baryshkov goto failed;
1276325ba852SDmitry Baryshkov }
1277325ba852SDmitry Baryshkov
1278325ba852SDmitry Baryshkov ret = 0;
1279325ba852SDmitry Baryshkov
1280325ba852SDmitry Baryshkov failed:
1281325ba852SDmitry Baryshkov mutex_unlock(&priv->edid_mutex);
1282325ba852SDmitry Baryshkov return ret;
1283325ba852SDmitry Baryshkov }
1284325ba852SDmitry Baryshkov
tda998x_connector_get_modes(struct drm_connector * connector)1285325ba852SDmitry Baryshkov static int tda998x_connector_get_modes(struct drm_connector *connector)
1286325ba852SDmitry Baryshkov {
1287325ba852SDmitry Baryshkov struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
1288325ba852SDmitry Baryshkov const struct drm_edid *drm_edid;
1289325ba852SDmitry Baryshkov int n;
1290325ba852SDmitry Baryshkov
1291325ba852SDmitry Baryshkov /*
1292325ba852SDmitry Baryshkov * If we get killed while waiting for the HPD timeout, return
1293325ba852SDmitry Baryshkov * no modes found: we are not in a restartable path, so we
1294325ba852SDmitry Baryshkov * can't handle signals gracefully.
1295325ba852SDmitry Baryshkov */
1296325ba852SDmitry Baryshkov if (tda998x_edid_delay_wait(priv))
1297325ba852SDmitry Baryshkov return 0;
1298325ba852SDmitry Baryshkov
1299325ba852SDmitry Baryshkov if (priv->rev == TDA19988)
1300325ba852SDmitry Baryshkov reg_clear(priv, REG_TX4, TX4_PD_RAM);
1301325ba852SDmitry Baryshkov
1302325ba852SDmitry Baryshkov drm_edid = drm_edid_read_custom(connector, read_edid_block, priv);
1303325ba852SDmitry Baryshkov
1304325ba852SDmitry Baryshkov if (priv->rev == TDA19988)
1305325ba852SDmitry Baryshkov reg_set(priv, REG_TX4, TX4_PD_RAM);
1306325ba852SDmitry Baryshkov
1307325ba852SDmitry Baryshkov drm_edid_connector_update(connector, drm_edid);
1308325ba852SDmitry Baryshkov cec_notifier_set_phys_addr(priv->cec_notify,
1309325ba852SDmitry Baryshkov connector->display_info.source_physical_address);
1310325ba852SDmitry Baryshkov
1311325ba852SDmitry Baryshkov if (!drm_edid) {
1312325ba852SDmitry Baryshkov dev_warn(&priv->hdmi->dev, "failed to read EDID\n");
1313325ba852SDmitry Baryshkov return 0;
1314325ba852SDmitry Baryshkov }
1315325ba852SDmitry Baryshkov
1316325ba852SDmitry Baryshkov mutex_lock(&priv->audio_mutex);
1317325ba852SDmitry Baryshkov n = drm_edid_connector_add_modes(connector);
1318325ba852SDmitry Baryshkov priv->sink_has_audio = connector->display_info.has_audio;
1319325ba852SDmitry Baryshkov mutex_unlock(&priv->audio_mutex);
1320325ba852SDmitry Baryshkov
1321325ba852SDmitry Baryshkov drm_edid_free(drm_edid);
1322325ba852SDmitry Baryshkov
1323325ba852SDmitry Baryshkov return n;
1324325ba852SDmitry Baryshkov }
1325325ba852SDmitry Baryshkov
1326325ba852SDmitry Baryshkov static struct drm_encoder *
tda998x_connector_best_encoder(struct drm_connector * connector)1327325ba852SDmitry Baryshkov tda998x_connector_best_encoder(struct drm_connector *connector)
1328325ba852SDmitry Baryshkov {
1329325ba852SDmitry Baryshkov struct tda998x_priv *priv = conn_to_tda998x_priv(connector);
1330325ba852SDmitry Baryshkov
1331325ba852SDmitry Baryshkov return priv->bridge.encoder;
1332325ba852SDmitry Baryshkov }
1333325ba852SDmitry Baryshkov
1334325ba852SDmitry Baryshkov static
1335325ba852SDmitry Baryshkov const struct drm_connector_helper_funcs tda998x_connector_helper_funcs = {
1336325ba852SDmitry Baryshkov .get_modes = tda998x_connector_get_modes,
1337325ba852SDmitry Baryshkov .best_encoder = tda998x_connector_best_encoder,
1338325ba852SDmitry Baryshkov };
1339325ba852SDmitry Baryshkov
tda998x_connector_init(struct tda998x_priv * priv,struct drm_device * drm)1340325ba852SDmitry Baryshkov static int tda998x_connector_init(struct tda998x_priv *priv,
1341325ba852SDmitry Baryshkov struct drm_device *drm)
1342325ba852SDmitry Baryshkov {
1343325ba852SDmitry Baryshkov struct drm_connector *connector = &priv->connector;
1344325ba852SDmitry Baryshkov int ret;
1345325ba852SDmitry Baryshkov
1346325ba852SDmitry Baryshkov connector->interlace_allowed = 1;
1347325ba852SDmitry Baryshkov
1348325ba852SDmitry Baryshkov if (priv->hdmi->irq)
1349325ba852SDmitry Baryshkov connector->polled = DRM_CONNECTOR_POLL_HPD;
1350325ba852SDmitry Baryshkov else
1351325ba852SDmitry Baryshkov connector->polled = DRM_CONNECTOR_POLL_CONNECT |
1352325ba852SDmitry Baryshkov DRM_CONNECTOR_POLL_DISCONNECT;
1353325ba852SDmitry Baryshkov
1354325ba852SDmitry Baryshkov drm_connector_helper_add(connector, &tda998x_connector_helper_funcs);
1355325ba852SDmitry Baryshkov ret = drm_connector_init(drm, connector, &tda998x_connector_funcs,
1356325ba852SDmitry Baryshkov DRM_MODE_CONNECTOR_HDMIA);
1357325ba852SDmitry Baryshkov if (ret)
1358325ba852SDmitry Baryshkov return ret;
1359325ba852SDmitry Baryshkov
1360325ba852SDmitry Baryshkov drm_connector_attach_encoder(&priv->connector,
1361325ba852SDmitry Baryshkov priv->bridge.encoder);
1362325ba852SDmitry Baryshkov
1363325ba852SDmitry Baryshkov return 0;
1364325ba852SDmitry Baryshkov }
1365325ba852SDmitry Baryshkov
1366325ba852SDmitry Baryshkov /* DRM bridge functions */
1367325ba852SDmitry Baryshkov
tda998x_bridge_attach(struct drm_bridge * bridge,struct drm_encoder * encoder,enum drm_bridge_attach_flags flags)1368325ba852SDmitry Baryshkov static int tda998x_bridge_attach(struct drm_bridge *bridge,
136998007a0dSMaxime Ripard struct drm_encoder *encoder,
1370325ba852SDmitry Baryshkov enum drm_bridge_attach_flags flags)
1371325ba852SDmitry Baryshkov {
1372325ba852SDmitry Baryshkov struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
1373325ba852SDmitry Baryshkov
1374325ba852SDmitry Baryshkov if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
1375325ba852SDmitry Baryshkov DRM_ERROR("Fix bridge driver to make connector optional!");
1376325ba852SDmitry Baryshkov return -EINVAL;
1377325ba852SDmitry Baryshkov }
1378325ba852SDmitry Baryshkov
1379325ba852SDmitry Baryshkov return tda998x_connector_init(priv, bridge->dev);
1380325ba852SDmitry Baryshkov }
1381325ba852SDmitry Baryshkov
tda998x_bridge_detach(struct drm_bridge * bridge)1382325ba852SDmitry Baryshkov static void tda998x_bridge_detach(struct drm_bridge *bridge)
1383325ba852SDmitry Baryshkov {
1384325ba852SDmitry Baryshkov struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
1385325ba852SDmitry Baryshkov
1386325ba852SDmitry Baryshkov drm_connector_cleanup(&priv->connector);
1387325ba852SDmitry Baryshkov }
1388325ba852SDmitry Baryshkov
tda998x_bridge_mode_valid(struct drm_bridge * bridge,const struct drm_display_info * info,const struct drm_display_mode * mode)1389325ba852SDmitry Baryshkov static enum drm_mode_status tda998x_bridge_mode_valid(struct drm_bridge *bridge,
1390325ba852SDmitry Baryshkov const struct drm_display_info *info,
1391325ba852SDmitry Baryshkov const struct drm_display_mode *mode)
1392325ba852SDmitry Baryshkov {
1393325ba852SDmitry Baryshkov /* TDA19988 dotclock can go up to 165MHz */
1394325ba852SDmitry Baryshkov struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
1395325ba852SDmitry Baryshkov
1396325ba852SDmitry Baryshkov if (mode->clock > ((priv->rev == TDA19988) ? 165000 : 150000))
1397325ba852SDmitry Baryshkov return MODE_CLOCK_HIGH;
1398325ba852SDmitry Baryshkov if (mode->htotal >= BIT(13))
1399325ba852SDmitry Baryshkov return MODE_BAD_HVALUE;
1400325ba852SDmitry Baryshkov if (mode->vtotal >= BIT(11))
1401325ba852SDmitry Baryshkov return MODE_BAD_VVALUE;
1402325ba852SDmitry Baryshkov return MODE_OK;
1403325ba852SDmitry Baryshkov }
1404325ba852SDmitry Baryshkov
tda998x_bridge_enable(struct drm_bridge * bridge)1405325ba852SDmitry Baryshkov static void tda998x_bridge_enable(struct drm_bridge *bridge)
1406325ba852SDmitry Baryshkov {
1407325ba852SDmitry Baryshkov struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
1408325ba852SDmitry Baryshkov
1409325ba852SDmitry Baryshkov if (!priv->is_on) {
1410325ba852SDmitry Baryshkov /* enable video ports, audio will be enabled later */
1411325ba852SDmitry Baryshkov reg_write(priv, REG_ENA_VP_0, 0xff);
1412325ba852SDmitry Baryshkov reg_write(priv, REG_ENA_VP_1, 0xff);
1413325ba852SDmitry Baryshkov reg_write(priv, REG_ENA_VP_2, 0xff);
1414325ba852SDmitry Baryshkov /* set muxing after enabling ports: */
1415325ba852SDmitry Baryshkov reg_write(priv, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
1416325ba852SDmitry Baryshkov reg_write(priv, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
1417325ba852SDmitry Baryshkov reg_write(priv, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
1418325ba852SDmitry Baryshkov
1419325ba852SDmitry Baryshkov priv->is_on = true;
1420325ba852SDmitry Baryshkov }
1421325ba852SDmitry Baryshkov }
1422325ba852SDmitry Baryshkov
tda998x_bridge_disable(struct drm_bridge * bridge)1423325ba852SDmitry Baryshkov static void tda998x_bridge_disable(struct drm_bridge *bridge)
1424325ba852SDmitry Baryshkov {
1425325ba852SDmitry Baryshkov struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
1426325ba852SDmitry Baryshkov
1427325ba852SDmitry Baryshkov if (priv->is_on) {
1428325ba852SDmitry Baryshkov /* disable video ports */
1429325ba852SDmitry Baryshkov reg_write(priv, REG_ENA_VP_0, 0x00);
1430325ba852SDmitry Baryshkov reg_write(priv, REG_ENA_VP_1, 0x00);
1431325ba852SDmitry Baryshkov reg_write(priv, REG_ENA_VP_2, 0x00);
1432325ba852SDmitry Baryshkov
1433325ba852SDmitry Baryshkov priv->is_on = false;
1434325ba852SDmitry Baryshkov }
1435325ba852SDmitry Baryshkov }
1436325ba852SDmitry Baryshkov
tda998x_bridge_mode_set(struct drm_bridge * bridge,const struct drm_display_mode * mode,const struct drm_display_mode * adjusted_mode)1437325ba852SDmitry Baryshkov static void tda998x_bridge_mode_set(struct drm_bridge *bridge,
1438325ba852SDmitry Baryshkov const struct drm_display_mode *mode,
1439325ba852SDmitry Baryshkov const struct drm_display_mode *adjusted_mode)
1440325ba852SDmitry Baryshkov {
1441325ba852SDmitry Baryshkov struct tda998x_priv *priv = bridge_to_tda998x_priv(bridge);
1442325ba852SDmitry Baryshkov unsigned long tmds_clock;
1443325ba852SDmitry Baryshkov u16 ref_pix, ref_line, n_pix, n_line;
1444325ba852SDmitry Baryshkov u16 hs_pix_s, hs_pix_e;
1445325ba852SDmitry Baryshkov u16 vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e;
1446325ba852SDmitry Baryshkov u16 vs2_pix_s, vs2_pix_e, vs2_line_s, vs2_line_e;
1447325ba852SDmitry Baryshkov u16 vwin1_line_s, vwin1_line_e;
1448325ba852SDmitry Baryshkov u16 vwin2_line_s, vwin2_line_e;
1449325ba852SDmitry Baryshkov u16 de_pix_s, de_pix_e;
1450325ba852SDmitry Baryshkov u8 reg, div, rep, sel_clk;
1451325ba852SDmitry Baryshkov
1452325ba852SDmitry Baryshkov /*
1453325ba852SDmitry Baryshkov * Since we are "computer" like, our source invariably produces
1454325ba852SDmitry Baryshkov * full-range RGB. If the monitor supports full-range, then use
1455325ba852SDmitry Baryshkov * it, otherwise reduce to limited-range.
1456325ba852SDmitry Baryshkov */
1457325ba852SDmitry Baryshkov priv->rgb_quant_range =
1458325ba852SDmitry Baryshkov priv->connector.display_info.rgb_quant_range_selectable ?
1459325ba852SDmitry Baryshkov HDMI_QUANTIZATION_RANGE_FULL :
1460325ba852SDmitry Baryshkov drm_default_rgb_quant_range(adjusted_mode);
1461325ba852SDmitry Baryshkov
1462325ba852SDmitry Baryshkov /*
1463325ba852SDmitry Baryshkov * Internally TDA998x is using ITU-R BT.656 style sync but
1464325ba852SDmitry Baryshkov * we get VESA style sync. TDA998x is using a reference pixel
1465325ba852SDmitry Baryshkov * relative to ITU to sync to the input frame and for output
1466325ba852SDmitry Baryshkov * sync generation. Currently, we are using reference detection
1467325ba852SDmitry Baryshkov * from HS/VS, i.e. REFPIX/REFLINE denote frame start sync point
1468325ba852SDmitry Baryshkov * which is position of rising VS with coincident rising HS.
1469325ba852SDmitry Baryshkov *
1470325ba852SDmitry Baryshkov * Now there is some issues to take care of:
1471325ba852SDmitry Baryshkov * - HDMI data islands require sync-before-active
1472325ba852SDmitry Baryshkov * - TDA998x register values must be > 0 to be enabled
1473325ba852SDmitry Baryshkov * - REFLINE needs an additional offset of +1
1474325ba852SDmitry Baryshkov * - REFPIX needs an addtional offset of +1 for UYUV and +3 for RGB
1475325ba852SDmitry Baryshkov *
1476325ba852SDmitry Baryshkov * So we add +1 to all horizontal and vertical register values,
1477325ba852SDmitry Baryshkov * plus an additional +3 for REFPIX as we are using RGB input only.
1478325ba852SDmitry Baryshkov */
1479325ba852SDmitry Baryshkov n_pix = mode->htotal;
1480325ba852SDmitry Baryshkov n_line = mode->vtotal;
1481325ba852SDmitry Baryshkov
1482325ba852SDmitry Baryshkov hs_pix_e = mode->hsync_end - mode->hdisplay;
1483325ba852SDmitry Baryshkov hs_pix_s = mode->hsync_start - mode->hdisplay;
1484325ba852SDmitry Baryshkov de_pix_e = mode->htotal;
1485325ba852SDmitry Baryshkov de_pix_s = mode->htotal - mode->hdisplay;
1486325ba852SDmitry Baryshkov ref_pix = 3 + hs_pix_s;
1487325ba852SDmitry Baryshkov
1488325ba852SDmitry Baryshkov /*
1489325ba852SDmitry Baryshkov * Attached LCD controllers may generate broken sync. Allow
1490325ba852SDmitry Baryshkov * those to adjust the position of the rising VS edge by adding
1491325ba852SDmitry Baryshkov * HSKEW to ref_pix.
1492325ba852SDmitry Baryshkov */
1493325ba852SDmitry Baryshkov if (adjusted_mode->flags & DRM_MODE_FLAG_HSKEW)
1494325ba852SDmitry Baryshkov ref_pix += adjusted_mode->hskew;
1495325ba852SDmitry Baryshkov
1496325ba852SDmitry Baryshkov if ((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) {
1497325ba852SDmitry Baryshkov ref_line = 1 + mode->vsync_start - mode->vdisplay;
1498325ba852SDmitry Baryshkov vwin1_line_s = mode->vtotal - mode->vdisplay - 1;
1499325ba852SDmitry Baryshkov vwin1_line_e = vwin1_line_s + mode->vdisplay;
1500325ba852SDmitry Baryshkov vs1_pix_s = vs1_pix_e = hs_pix_s;
1501325ba852SDmitry Baryshkov vs1_line_s = mode->vsync_start - mode->vdisplay;
1502325ba852SDmitry Baryshkov vs1_line_e = vs1_line_s +
1503325ba852SDmitry Baryshkov mode->vsync_end - mode->vsync_start;
1504325ba852SDmitry Baryshkov vwin2_line_s = vwin2_line_e = 0;
1505325ba852SDmitry Baryshkov vs2_pix_s = vs2_pix_e = 0;
1506325ba852SDmitry Baryshkov vs2_line_s = vs2_line_e = 0;
1507325ba852SDmitry Baryshkov } else {
1508325ba852SDmitry Baryshkov ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2;
1509325ba852SDmitry Baryshkov vwin1_line_s = (mode->vtotal - mode->vdisplay)/2;
1510325ba852SDmitry Baryshkov vwin1_line_e = vwin1_line_s + mode->vdisplay/2;
1511325ba852SDmitry Baryshkov vs1_pix_s = vs1_pix_e = hs_pix_s;
1512325ba852SDmitry Baryshkov vs1_line_s = (mode->vsync_start - mode->vdisplay)/2;
1513325ba852SDmitry Baryshkov vs1_line_e = vs1_line_s +
1514325ba852SDmitry Baryshkov (mode->vsync_end - mode->vsync_start)/2;
1515325ba852SDmitry Baryshkov vwin2_line_s = vwin1_line_s + mode->vtotal/2;
1516325ba852SDmitry Baryshkov vwin2_line_e = vwin2_line_s + mode->vdisplay/2;
1517325ba852SDmitry Baryshkov vs2_pix_s = vs2_pix_e = hs_pix_s + mode->htotal/2;
1518325ba852SDmitry Baryshkov vs2_line_s = vs1_line_s + mode->vtotal/2 ;
1519325ba852SDmitry Baryshkov vs2_line_e = vs2_line_s +
1520325ba852SDmitry Baryshkov (mode->vsync_end - mode->vsync_start)/2;
1521325ba852SDmitry Baryshkov }
1522325ba852SDmitry Baryshkov
1523325ba852SDmitry Baryshkov /*
1524325ba852SDmitry Baryshkov * Select pixel repeat depending on the double-clock flag
1525325ba852SDmitry Baryshkov * (which means we have to repeat each pixel once.)
1526325ba852SDmitry Baryshkov */
1527325ba852SDmitry Baryshkov rep = mode->flags & DRM_MODE_FLAG_DBLCLK ? 1 : 0;
1528325ba852SDmitry Baryshkov sel_clk = SEL_CLK_ENA_SC_CLK | SEL_CLK_SEL_CLK1 |
1529325ba852SDmitry Baryshkov SEL_CLK_SEL_VRF_CLK(rep ? 2 : 0);
1530325ba852SDmitry Baryshkov
1531325ba852SDmitry Baryshkov /* the TMDS clock is scaled up by the pixel repeat */
1532325ba852SDmitry Baryshkov tmds_clock = mode->clock * (1 + rep);
1533325ba852SDmitry Baryshkov
1534325ba852SDmitry Baryshkov /*
1535325ba852SDmitry Baryshkov * The divisor is power-of-2. The TDA9983B datasheet gives
1536325ba852SDmitry Baryshkov * this as ranges of Msample/s, which is 10x the TMDS clock:
1537325ba852SDmitry Baryshkov * 0 - 800 to 1500 Msample/s
1538325ba852SDmitry Baryshkov * 1 - 400 to 800 Msample/s
1539325ba852SDmitry Baryshkov * 2 - 200 to 400 Msample/s
1540325ba852SDmitry Baryshkov * 3 - as 2 above
1541325ba852SDmitry Baryshkov */
1542325ba852SDmitry Baryshkov for (div = 0; div < 3; div++)
1543325ba852SDmitry Baryshkov if (80000 >> div <= tmds_clock)
1544325ba852SDmitry Baryshkov break;
1545325ba852SDmitry Baryshkov
1546325ba852SDmitry Baryshkov mutex_lock(&priv->audio_mutex);
1547325ba852SDmitry Baryshkov
1548325ba852SDmitry Baryshkov priv->tmds_clock = tmds_clock;
1549325ba852SDmitry Baryshkov
1550325ba852SDmitry Baryshkov /* mute the audio FIFO: */
1551325ba852SDmitry Baryshkov reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
1552325ba852SDmitry Baryshkov
1553325ba852SDmitry Baryshkov /* set HDMI HDCP mode off: */
1554325ba852SDmitry Baryshkov reg_write(priv, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
1555325ba852SDmitry Baryshkov reg_clear(priv, REG_TX33, TX33_HDMI);
1556325ba852SDmitry Baryshkov reg_write(priv, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0));
1557325ba852SDmitry Baryshkov
1558325ba852SDmitry Baryshkov /* no pre-filter or interpolator: */
1559325ba852SDmitry Baryshkov reg_write(priv, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
1560325ba852SDmitry Baryshkov HVF_CNTRL_0_INTPOL(0));
1561325ba852SDmitry Baryshkov reg_set(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_PREFILT);
1562325ba852SDmitry Baryshkov reg_write(priv, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
1563325ba852SDmitry Baryshkov reg_write(priv, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
1564325ba852SDmitry Baryshkov VIP_CNTRL_4_BLC(0));
1565325ba852SDmitry Baryshkov
1566325ba852SDmitry Baryshkov reg_clear(priv, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ);
1567325ba852SDmitry Baryshkov reg_clear(priv, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR |
1568325ba852SDmitry Baryshkov PLL_SERIAL_3_SRL_DE);
1569325ba852SDmitry Baryshkov reg_write(priv, REG_SERIALIZER, 0);
1570325ba852SDmitry Baryshkov reg_write(priv, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0));
1571325ba852SDmitry Baryshkov
1572325ba852SDmitry Baryshkov reg_write(priv, REG_RPT_CNTRL, RPT_CNTRL_REPEAT(rep));
1573325ba852SDmitry Baryshkov reg_write(priv, REG_SEL_CLK, sel_clk);
1574325ba852SDmitry Baryshkov reg_write(priv, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
1575325ba852SDmitry Baryshkov PLL_SERIAL_2_SRL_PR(rep));
1576325ba852SDmitry Baryshkov
1577325ba852SDmitry Baryshkov /* set color matrix according to output rgb quant range */
1578325ba852SDmitry Baryshkov if (priv->rgb_quant_range == HDMI_QUANTIZATION_RANGE_LIMITED) {
1579325ba852SDmitry Baryshkov static u8 tda998x_full_to_limited_range[] = {
1580325ba852SDmitry Baryshkov MAT_CONTRL_MAT_SC(2),
1581325ba852SDmitry Baryshkov 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1582325ba852SDmitry Baryshkov 0x03, 0x6f, 0x00, 0x00, 0x00, 0x00,
1583325ba852SDmitry Baryshkov 0x00, 0x00, 0x03, 0x6f, 0x00, 0x00,
1584325ba852SDmitry Baryshkov 0x00, 0x00, 0x00, 0x00, 0x03, 0x6f,
1585325ba852SDmitry Baryshkov 0x00, 0x40, 0x00, 0x40, 0x00, 0x40
1586325ba852SDmitry Baryshkov };
1587325ba852SDmitry Baryshkov reg_clear(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_CSC);
1588325ba852SDmitry Baryshkov reg_write_range(priv, REG_MAT_CONTRL,
1589325ba852SDmitry Baryshkov tda998x_full_to_limited_range,
1590325ba852SDmitry Baryshkov sizeof(tda998x_full_to_limited_range));
1591325ba852SDmitry Baryshkov } else {
1592325ba852SDmitry Baryshkov reg_write(priv, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP |
1593325ba852SDmitry Baryshkov MAT_CONTRL_MAT_SC(1));
1594325ba852SDmitry Baryshkov reg_set(priv, REG_FEAT_POWERDOWN, FEAT_POWERDOWN_CSC);
1595325ba852SDmitry Baryshkov }
1596325ba852SDmitry Baryshkov
1597325ba852SDmitry Baryshkov /* set BIAS tmds value: */
1598325ba852SDmitry Baryshkov reg_write(priv, REG_ANA_GENERAL, 0x09);
1599325ba852SDmitry Baryshkov
1600325ba852SDmitry Baryshkov /*
1601325ba852SDmitry Baryshkov * Sync on rising HSYNC/VSYNC
1602325ba852SDmitry Baryshkov */
1603325ba852SDmitry Baryshkov reg = VIP_CNTRL_3_SYNC_HS;
1604325ba852SDmitry Baryshkov
1605325ba852SDmitry Baryshkov /*
1606325ba852SDmitry Baryshkov * TDA19988 requires high-active sync at input stage,
1607325ba852SDmitry Baryshkov * so invert low-active sync provided by master encoder here
1608325ba852SDmitry Baryshkov */
1609325ba852SDmitry Baryshkov if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1610325ba852SDmitry Baryshkov reg |= VIP_CNTRL_3_H_TGL;
1611325ba852SDmitry Baryshkov if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1612325ba852SDmitry Baryshkov reg |= VIP_CNTRL_3_V_TGL;
1613325ba852SDmitry Baryshkov reg_write(priv, REG_VIP_CNTRL_3, reg);
1614325ba852SDmitry Baryshkov
1615325ba852SDmitry Baryshkov reg_write(priv, REG_VIDFORMAT, 0x00);
1616325ba852SDmitry Baryshkov reg_write16(priv, REG_REFPIX_MSB, ref_pix);
1617325ba852SDmitry Baryshkov reg_write16(priv, REG_REFLINE_MSB, ref_line);
1618325ba852SDmitry Baryshkov reg_write16(priv, REG_NPIX_MSB, n_pix);
1619325ba852SDmitry Baryshkov reg_write16(priv, REG_NLINE_MSB, n_line);
1620325ba852SDmitry Baryshkov reg_write16(priv, REG_VS_LINE_STRT_1_MSB, vs1_line_s);
1621325ba852SDmitry Baryshkov reg_write16(priv, REG_VS_PIX_STRT_1_MSB, vs1_pix_s);
1622325ba852SDmitry Baryshkov reg_write16(priv, REG_VS_LINE_END_1_MSB, vs1_line_e);
1623325ba852SDmitry Baryshkov reg_write16(priv, REG_VS_PIX_END_1_MSB, vs1_pix_e);
1624325ba852SDmitry Baryshkov reg_write16(priv, REG_VS_LINE_STRT_2_MSB, vs2_line_s);
1625325ba852SDmitry Baryshkov reg_write16(priv, REG_VS_PIX_STRT_2_MSB, vs2_pix_s);
1626325ba852SDmitry Baryshkov reg_write16(priv, REG_VS_LINE_END_2_MSB, vs2_line_e);
1627325ba852SDmitry Baryshkov reg_write16(priv, REG_VS_PIX_END_2_MSB, vs2_pix_e);
1628325ba852SDmitry Baryshkov reg_write16(priv, REG_HS_PIX_START_MSB, hs_pix_s);
1629325ba852SDmitry Baryshkov reg_write16(priv, REG_HS_PIX_STOP_MSB, hs_pix_e);
1630325ba852SDmitry Baryshkov reg_write16(priv, REG_VWIN_START_1_MSB, vwin1_line_s);
1631325ba852SDmitry Baryshkov reg_write16(priv, REG_VWIN_END_1_MSB, vwin1_line_e);
1632325ba852SDmitry Baryshkov reg_write16(priv, REG_VWIN_START_2_MSB, vwin2_line_s);
1633325ba852SDmitry Baryshkov reg_write16(priv, REG_VWIN_END_2_MSB, vwin2_line_e);
1634325ba852SDmitry Baryshkov reg_write16(priv, REG_DE_START_MSB, de_pix_s);
1635325ba852SDmitry Baryshkov reg_write16(priv, REG_DE_STOP_MSB, de_pix_e);
1636325ba852SDmitry Baryshkov
1637325ba852SDmitry Baryshkov if (priv->rev == TDA19988) {
1638325ba852SDmitry Baryshkov /* let incoming pixels fill the active space (if any) */
1639325ba852SDmitry Baryshkov reg_write(priv, REG_ENABLE_SPACE, 0x00);
1640325ba852SDmitry Baryshkov }
1641325ba852SDmitry Baryshkov
1642325ba852SDmitry Baryshkov /*
1643325ba852SDmitry Baryshkov * Always generate sync polarity relative to input sync and
1644325ba852SDmitry Baryshkov * revert input stage toggled sync at output stage
1645325ba852SDmitry Baryshkov */
1646325ba852SDmitry Baryshkov reg = TBG_CNTRL_1_DWIN_DIS | TBG_CNTRL_1_TGL_EN;
1647325ba852SDmitry Baryshkov if (mode->flags & DRM_MODE_FLAG_NHSYNC)
1648325ba852SDmitry Baryshkov reg |= TBG_CNTRL_1_H_TGL;
1649325ba852SDmitry Baryshkov if (mode->flags & DRM_MODE_FLAG_NVSYNC)
1650325ba852SDmitry Baryshkov reg |= TBG_CNTRL_1_V_TGL;
1651325ba852SDmitry Baryshkov reg_write(priv, REG_TBG_CNTRL_1, reg);
1652325ba852SDmitry Baryshkov
1653325ba852SDmitry Baryshkov /* must be last register set: */
1654325ba852SDmitry Baryshkov reg_write(priv, REG_TBG_CNTRL_0, 0);
1655325ba852SDmitry Baryshkov
1656325ba852SDmitry Baryshkov /* CEA-861B section 6 says that:
1657325ba852SDmitry Baryshkov * CEA version 1 (CEA-861) has no support for infoframes.
1658325ba852SDmitry Baryshkov * CEA version 2 (CEA-861A) supports version 1 AVI infoframes,
1659325ba852SDmitry Baryshkov * and optional basic audio.
1660325ba852SDmitry Baryshkov * CEA version 3 (CEA-861B) supports version 1 and 2 AVI infoframes,
1661325ba852SDmitry Baryshkov * and optional digital audio, with audio infoframes.
1662325ba852SDmitry Baryshkov *
1663325ba852SDmitry Baryshkov * Since we only support generation of version 2 AVI infoframes,
1664325ba852SDmitry Baryshkov * ignore CEA version 2 and below (iow, behave as if we're a
1665325ba852SDmitry Baryshkov * CEA-861 source.)
1666325ba852SDmitry Baryshkov */
1667325ba852SDmitry Baryshkov priv->supports_infoframes = priv->connector.display_info.cea_rev >= 3;
1668325ba852SDmitry Baryshkov
1669325ba852SDmitry Baryshkov if (priv->supports_infoframes) {
1670325ba852SDmitry Baryshkov /* We need to turn HDMI HDCP stuff on to get audio through */
1671325ba852SDmitry Baryshkov reg &= ~TBG_CNTRL_1_DWIN_DIS;
1672325ba852SDmitry Baryshkov reg_write(priv, REG_TBG_CNTRL_1, reg);
1673325ba852SDmitry Baryshkov reg_write(priv, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(1));
1674325ba852SDmitry Baryshkov reg_set(priv, REG_TX33, TX33_HDMI);
1675325ba852SDmitry Baryshkov
1676325ba852SDmitry Baryshkov tda998x_write_avi(priv, adjusted_mode);
1677325ba852SDmitry Baryshkov tda998x_write_vsi(priv, adjusted_mode);
1678325ba852SDmitry Baryshkov
1679325ba852SDmitry Baryshkov if (priv->sink_has_audio)
1680325ba852SDmitry Baryshkov tda998x_configure_audio(priv);
1681325ba852SDmitry Baryshkov }
1682325ba852SDmitry Baryshkov
1683325ba852SDmitry Baryshkov mutex_unlock(&priv->audio_mutex);
1684325ba852SDmitry Baryshkov }
1685325ba852SDmitry Baryshkov
1686325ba852SDmitry Baryshkov static const struct drm_bridge_funcs tda998x_bridge_funcs = {
1687325ba852SDmitry Baryshkov .attach = tda998x_bridge_attach,
1688325ba852SDmitry Baryshkov .detach = tda998x_bridge_detach,
1689325ba852SDmitry Baryshkov .mode_valid = tda998x_bridge_mode_valid,
1690325ba852SDmitry Baryshkov .disable = tda998x_bridge_disable,
1691325ba852SDmitry Baryshkov .mode_set = tda998x_bridge_mode_set,
1692325ba852SDmitry Baryshkov .enable = tda998x_bridge_enable,
1693325ba852SDmitry Baryshkov };
1694325ba852SDmitry Baryshkov
1695325ba852SDmitry Baryshkov /* I2C driver functions */
1696325ba852SDmitry Baryshkov
tda998x_get_audio_ports(struct tda998x_priv * priv,struct device_node * np)1697325ba852SDmitry Baryshkov static int tda998x_get_audio_ports(struct tda998x_priv *priv,
1698325ba852SDmitry Baryshkov struct device_node *np)
1699325ba852SDmitry Baryshkov {
1700325ba852SDmitry Baryshkov const u32 *port_data;
1701325ba852SDmitry Baryshkov u32 size;
1702325ba852SDmitry Baryshkov int i;
1703325ba852SDmitry Baryshkov
1704325ba852SDmitry Baryshkov port_data = of_get_property(np, "audio-ports", &size);
1705325ba852SDmitry Baryshkov if (!port_data)
1706325ba852SDmitry Baryshkov return 0;
1707325ba852SDmitry Baryshkov
1708325ba852SDmitry Baryshkov size /= sizeof(u32);
1709325ba852SDmitry Baryshkov if (size > 2 * ARRAY_SIZE(priv->audio_port_enable) || size % 2 != 0) {
1710325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev,
1711325ba852SDmitry Baryshkov "Bad number of elements in audio-ports dt-property\n");
1712325ba852SDmitry Baryshkov return -EINVAL;
1713325ba852SDmitry Baryshkov }
1714325ba852SDmitry Baryshkov
1715325ba852SDmitry Baryshkov size /= 2;
1716325ba852SDmitry Baryshkov
1717325ba852SDmitry Baryshkov for (i = 0; i < size; i++) {
1718325ba852SDmitry Baryshkov unsigned int route;
1719325ba852SDmitry Baryshkov u8 afmt = be32_to_cpup(&port_data[2*i]);
1720325ba852SDmitry Baryshkov u8 ena_ap = be32_to_cpup(&port_data[2*i+1]);
1721325ba852SDmitry Baryshkov
1722325ba852SDmitry Baryshkov switch (afmt) {
1723325ba852SDmitry Baryshkov case TDA998x_I2S:
1724325ba852SDmitry Baryshkov route = AUDIO_ROUTE_I2S;
1725325ba852SDmitry Baryshkov break;
1726325ba852SDmitry Baryshkov case TDA998x_SPDIF:
1727325ba852SDmitry Baryshkov route = AUDIO_ROUTE_SPDIF;
1728325ba852SDmitry Baryshkov break;
1729325ba852SDmitry Baryshkov default:
1730325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev,
1731325ba852SDmitry Baryshkov "Bad audio format %u\n", afmt);
1732325ba852SDmitry Baryshkov return -EINVAL;
1733325ba852SDmitry Baryshkov }
1734325ba852SDmitry Baryshkov
1735325ba852SDmitry Baryshkov if (!ena_ap) {
1736325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev, "invalid zero port config\n");
1737325ba852SDmitry Baryshkov continue;
1738325ba852SDmitry Baryshkov }
1739325ba852SDmitry Baryshkov
1740325ba852SDmitry Baryshkov if (priv->audio_port_enable[route]) {
1741325ba852SDmitry Baryshkov dev_err(&priv->hdmi->dev,
1742325ba852SDmitry Baryshkov "%s format already configured\n",
1743325ba852SDmitry Baryshkov route == AUDIO_ROUTE_SPDIF ? "SPDIF" : "I2S");
1744325ba852SDmitry Baryshkov return -EINVAL;
1745325ba852SDmitry Baryshkov }
1746325ba852SDmitry Baryshkov
1747325ba852SDmitry Baryshkov priv->audio_port_enable[route] = ena_ap;
1748325ba852SDmitry Baryshkov }
1749325ba852SDmitry Baryshkov return 0;
1750325ba852SDmitry Baryshkov }
1751325ba852SDmitry Baryshkov
tda998x_destroy(struct device * dev)1752325ba852SDmitry Baryshkov static void tda998x_destroy(struct device *dev)
1753325ba852SDmitry Baryshkov {
1754325ba852SDmitry Baryshkov struct tda998x_priv *priv = dev_get_drvdata(dev);
1755325ba852SDmitry Baryshkov
1756325ba852SDmitry Baryshkov drm_bridge_remove(&priv->bridge);
1757325ba852SDmitry Baryshkov
1758325ba852SDmitry Baryshkov /* disable all IRQs and free the IRQ handler */
1759325ba852SDmitry Baryshkov cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
1760325ba852SDmitry Baryshkov reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
1761325ba852SDmitry Baryshkov
1762325ba852SDmitry Baryshkov if (priv->audio_pdev)
1763325ba852SDmitry Baryshkov platform_device_unregister(priv->audio_pdev);
1764325ba852SDmitry Baryshkov
1765325ba852SDmitry Baryshkov if (priv->hdmi->irq)
1766325ba852SDmitry Baryshkov free_irq(priv->hdmi->irq, priv);
1767325ba852SDmitry Baryshkov
17688fa7292fSThomas Gleixner timer_delete_sync(&priv->edid_delay_timer);
1769325ba852SDmitry Baryshkov cancel_work_sync(&priv->detect_work);
1770325ba852SDmitry Baryshkov
1771325ba852SDmitry Baryshkov i2c_unregister_device(priv->cec);
1772325ba852SDmitry Baryshkov
1773325ba852SDmitry Baryshkov cec_notifier_conn_unregister(priv->cec_notify);
1774325ba852SDmitry Baryshkov }
1775325ba852SDmitry Baryshkov
tda998x_create(struct device * dev)1776325ba852SDmitry Baryshkov static int tda998x_create(struct device *dev)
1777325ba852SDmitry Baryshkov {
1778325ba852SDmitry Baryshkov struct i2c_client *client = to_i2c_client(dev);
1779325ba852SDmitry Baryshkov struct device_node *np = client->dev.of_node;
1780325ba852SDmitry Baryshkov struct i2c_board_info cec_info;
1781325ba852SDmitry Baryshkov struct tda998x_priv *priv;
1782325ba852SDmitry Baryshkov u32 video;
1783325ba852SDmitry Baryshkov int rev_lo, rev_hi, ret;
1784325ba852SDmitry Baryshkov
17857fe58bf1SLuca Ceresoli priv = devm_drm_bridge_alloc(dev, struct tda998x_priv, bridge, &tda998x_bridge_funcs);
17867fe58bf1SLuca Ceresoli if (IS_ERR(priv))
17877fe58bf1SLuca Ceresoli return PTR_ERR(priv);
1788325ba852SDmitry Baryshkov
1789325ba852SDmitry Baryshkov dev_set_drvdata(dev, priv);
1790325ba852SDmitry Baryshkov
1791325ba852SDmitry Baryshkov mutex_init(&priv->mutex); /* protect the page access */
1792325ba852SDmitry Baryshkov mutex_init(&priv->audio_mutex); /* protect access from audio thread */
1793325ba852SDmitry Baryshkov mutex_init(&priv->edid_mutex);
1794325ba852SDmitry Baryshkov INIT_LIST_HEAD(&priv->bridge.list);
1795325ba852SDmitry Baryshkov init_waitqueue_head(&priv->edid_delay_waitq);
1796325ba852SDmitry Baryshkov timer_setup(&priv->edid_delay_timer, tda998x_edid_delay_done, 0);
1797325ba852SDmitry Baryshkov INIT_WORK(&priv->detect_work, tda998x_detect_work);
1798325ba852SDmitry Baryshkov
1799325ba852SDmitry Baryshkov priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
1800325ba852SDmitry Baryshkov priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
1801325ba852SDmitry Baryshkov priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
1802325ba852SDmitry Baryshkov
1803325ba852SDmitry Baryshkov /* CEC I2C address bound to TDA998x I2C addr by configuration pins */
1804325ba852SDmitry Baryshkov priv->cec_addr = 0x34 + (client->addr & 0x03);
1805325ba852SDmitry Baryshkov priv->current_page = 0xff;
1806325ba852SDmitry Baryshkov priv->hdmi = client;
1807325ba852SDmitry Baryshkov
1808325ba852SDmitry Baryshkov /* wake up the device: */
1809325ba852SDmitry Baryshkov cec_write(priv, REG_CEC_ENAMODS,
1810325ba852SDmitry Baryshkov CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
1811325ba852SDmitry Baryshkov
1812325ba852SDmitry Baryshkov tda998x_reset(priv);
1813325ba852SDmitry Baryshkov
1814325ba852SDmitry Baryshkov /* read version: */
1815325ba852SDmitry Baryshkov rev_lo = reg_read(priv, REG_VERSION_LSB);
1816325ba852SDmitry Baryshkov if (rev_lo < 0) {
1817325ba852SDmitry Baryshkov dev_err(dev, "failed to read version: %d\n", rev_lo);
1818325ba852SDmitry Baryshkov return rev_lo;
1819325ba852SDmitry Baryshkov }
1820325ba852SDmitry Baryshkov
1821325ba852SDmitry Baryshkov rev_hi = reg_read(priv, REG_VERSION_MSB);
1822325ba852SDmitry Baryshkov if (rev_hi < 0) {
1823325ba852SDmitry Baryshkov dev_err(dev, "failed to read version: %d\n", rev_hi);
1824325ba852SDmitry Baryshkov return rev_hi;
1825325ba852SDmitry Baryshkov }
1826325ba852SDmitry Baryshkov
1827325ba852SDmitry Baryshkov priv->rev = rev_lo | rev_hi << 8;
1828325ba852SDmitry Baryshkov
1829325ba852SDmitry Baryshkov /* mask off feature bits: */
1830325ba852SDmitry Baryshkov priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */
1831325ba852SDmitry Baryshkov
1832325ba852SDmitry Baryshkov switch (priv->rev) {
1833325ba852SDmitry Baryshkov case TDA9989N2:
1834325ba852SDmitry Baryshkov dev_info(dev, "found TDA9989 n2");
1835325ba852SDmitry Baryshkov break;
1836325ba852SDmitry Baryshkov case TDA19989:
1837325ba852SDmitry Baryshkov dev_info(dev, "found TDA19989");
1838325ba852SDmitry Baryshkov break;
1839325ba852SDmitry Baryshkov case TDA19989N2:
1840325ba852SDmitry Baryshkov dev_info(dev, "found TDA19989 n2");
1841325ba852SDmitry Baryshkov break;
1842325ba852SDmitry Baryshkov case TDA19988:
1843325ba852SDmitry Baryshkov dev_info(dev, "found TDA19988");
1844325ba852SDmitry Baryshkov break;
1845325ba852SDmitry Baryshkov default:
1846325ba852SDmitry Baryshkov dev_err(dev, "found unsupported device: %04x\n", priv->rev);
1847325ba852SDmitry Baryshkov return -ENXIO;
1848325ba852SDmitry Baryshkov }
1849325ba852SDmitry Baryshkov
1850325ba852SDmitry Baryshkov /* after reset, enable DDC: */
1851325ba852SDmitry Baryshkov reg_write(priv, REG_DDC_DISABLE, 0x00);
1852325ba852SDmitry Baryshkov
1853325ba852SDmitry Baryshkov /* set clock on DDC channel: */
1854325ba852SDmitry Baryshkov reg_write(priv, REG_TX3, 39);
1855325ba852SDmitry Baryshkov
1856325ba852SDmitry Baryshkov /* if necessary, disable multi-master: */
1857325ba852SDmitry Baryshkov if (priv->rev == TDA19989)
1858325ba852SDmitry Baryshkov reg_set(priv, REG_I2C_MASTER, I2C_MASTER_DIS_MM);
1859325ba852SDmitry Baryshkov
1860325ba852SDmitry Baryshkov cec_write(priv, REG_CEC_FRO_IM_CLK_CTRL,
1861325ba852SDmitry Baryshkov CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
1862325ba852SDmitry Baryshkov
1863325ba852SDmitry Baryshkov /* ensure interrupts are disabled */
1864325ba852SDmitry Baryshkov cec_write(priv, REG_CEC_RXSHPDINTENA, 0);
1865325ba852SDmitry Baryshkov
1866325ba852SDmitry Baryshkov /* clear pending interrupts */
1867325ba852SDmitry Baryshkov cec_read(priv, REG_CEC_RXSHPDINT);
1868325ba852SDmitry Baryshkov reg_read(priv, REG_INT_FLAGS_0);
1869325ba852SDmitry Baryshkov reg_read(priv, REG_INT_FLAGS_1);
1870325ba852SDmitry Baryshkov reg_read(priv, REG_INT_FLAGS_2);
1871325ba852SDmitry Baryshkov
1872325ba852SDmitry Baryshkov /* initialize the optional IRQ */
1873325ba852SDmitry Baryshkov if (client->irq) {
1874325ba852SDmitry Baryshkov unsigned long irq_flags;
1875325ba852SDmitry Baryshkov
1876325ba852SDmitry Baryshkov /* init read EDID waitqueue and HDP work */
1877325ba852SDmitry Baryshkov init_waitqueue_head(&priv->wq_edid);
1878325ba852SDmitry Baryshkov
1879325ba852SDmitry Baryshkov irq_flags =
1880325ba852SDmitry Baryshkov irqd_get_trigger_type(irq_get_irq_data(client->irq));
1881325ba852SDmitry Baryshkov
1882325ba852SDmitry Baryshkov priv->cec_glue.irq_flags = irq_flags;
1883325ba852SDmitry Baryshkov
1884325ba852SDmitry Baryshkov irq_flags |= IRQF_SHARED | IRQF_ONESHOT;
1885325ba852SDmitry Baryshkov ret = request_threaded_irq(client->irq, NULL,
1886325ba852SDmitry Baryshkov tda998x_irq_thread, irq_flags,
1887325ba852SDmitry Baryshkov "tda998x", priv);
1888325ba852SDmitry Baryshkov if (ret) {
1889325ba852SDmitry Baryshkov dev_err(dev, "failed to request IRQ#%u: %d\n",
1890325ba852SDmitry Baryshkov client->irq, ret);
1891325ba852SDmitry Baryshkov goto err_irq;
1892325ba852SDmitry Baryshkov }
1893325ba852SDmitry Baryshkov
1894325ba852SDmitry Baryshkov /* enable HPD irq */
1895325ba852SDmitry Baryshkov cec_write(priv, REG_CEC_RXSHPDINTENA, CEC_RXSHPDLEV_HPD);
1896325ba852SDmitry Baryshkov }
1897325ba852SDmitry Baryshkov
1898325ba852SDmitry Baryshkov priv->cec_notify = cec_notifier_conn_register(dev, NULL, NULL);
1899325ba852SDmitry Baryshkov if (!priv->cec_notify) {
1900325ba852SDmitry Baryshkov ret = -ENOMEM;
1901325ba852SDmitry Baryshkov goto fail;
1902325ba852SDmitry Baryshkov }
1903325ba852SDmitry Baryshkov
1904325ba852SDmitry Baryshkov priv->cec_glue.parent = dev;
1905325ba852SDmitry Baryshkov priv->cec_glue.data = priv;
1906325ba852SDmitry Baryshkov priv->cec_glue.init = tda998x_cec_hook_init;
1907325ba852SDmitry Baryshkov priv->cec_glue.exit = tda998x_cec_hook_exit;
1908325ba852SDmitry Baryshkov priv->cec_glue.open = tda998x_cec_hook_open;
1909325ba852SDmitry Baryshkov priv->cec_glue.release = tda998x_cec_hook_release;
1910325ba852SDmitry Baryshkov
1911325ba852SDmitry Baryshkov /*
1912325ba852SDmitry Baryshkov * Some TDA998x are actually two I2C devices merged onto one piece
1913325ba852SDmitry Baryshkov * of silicon: TDA9989 and TDA19989 combine the HDMI transmitter
1914325ba852SDmitry Baryshkov * with a slightly modified TDA9950 CEC device. The CEC device
1915325ba852SDmitry Baryshkov * is at the TDA9950 address, with the address pins strapped across
1916325ba852SDmitry Baryshkov * to the TDA998x address pins. Hence, it always has the same
1917325ba852SDmitry Baryshkov * offset.
1918325ba852SDmitry Baryshkov */
1919325ba852SDmitry Baryshkov memset(&cec_info, 0, sizeof(cec_info));
1920325ba852SDmitry Baryshkov strscpy(cec_info.type, "tda9950", sizeof(cec_info.type));
1921325ba852SDmitry Baryshkov cec_info.addr = priv->cec_addr;
1922325ba852SDmitry Baryshkov cec_info.platform_data = &priv->cec_glue;
1923325ba852SDmitry Baryshkov cec_info.irq = client->irq;
1924325ba852SDmitry Baryshkov
1925325ba852SDmitry Baryshkov priv->cec = i2c_new_client_device(client->adapter, &cec_info);
1926325ba852SDmitry Baryshkov if (IS_ERR(priv->cec)) {
1927325ba852SDmitry Baryshkov ret = PTR_ERR(priv->cec);
1928325ba852SDmitry Baryshkov goto fail;
1929325ba852SDmitry Baryshkov }
1930325ba852SDmitry Baryshkov
1931325ba852SDmitry Baryshkov /* enable EDID read irq: */
1932325ba852SDmitry Baryshkov reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
1933325ba852SDmitry Baryshkov
1934325ba852SDmitry Baryshkov if (np) {
1935325ba852SDmitry Baryshkov /* get the device tree parameters */
1936325ba852SDmitry Baryshkov ret = of_property_read_u32(np, "video-ports", &video);
1937325ba852SDmitry Baryshkov if (ret == 0) {
1938325ba852SDmitry Baryshkov priv->vip_cntrl_0 = video >> 16;
1939325ba852SDmitry Baryshkov priv->vip_cntrl_1 = video >> 8;
1940325ba852SDmitry Baryshkov priv->vip_cntrl_2 = video;
1941325ba852SDmitry Baryshkov }
1942325ba852SDmitry Baryshkov
1943325ba852SDmitry Baryshkov ret = tda998x_get_audio_ports(priv, np);
1944325ba852SDmitry Baryshkov if (ret)
1945325ba852SDmitry Baryshkov goto fail;
1946325ba852SDmitry Baryshkov
1947325ba852SDmitry Baryshkov if (priv->audio_port_enable[AUDIO_ROUTE_I2S] ||
1948325ba852SDmitry Baryshkov priv->audio_port_enable[AUDIO_ROUTE_SPDIF])
1949325ba852SDmitry Baryshkov tda998x_audio_codec_init(priv, &client->dev);
1950325ba852SDmitry Baryshkov }
1951325ba852SDmitry Baryshkov
1952325ba852SDmitry Baryshkov #ifdef CONFIG_OF
1953325ba852SDmitry Baryshkov priv->bridge.of_node = dev->of_node;
1954325ba852SDmitry Baryshkov #endif
1955325ba852SDmitry Baryshkov
1956325ba852SDmitry Baryshkov drm_bridge_add(&priv->bridge);
1957325ba852SDmitry Baryshkov
1958325ba852SDmitry Baryshkov return 0;
1959325ba852SDmitry Baryshkov
1960325ba852SDmitry Baryshkov fail:
1961325ba852SDmitry Baryshkov tda998x_destroy(dev);
1962325ba852SDmitry Baryshkov err_irq:
1963325ba852SDmitry Baryshkov return ret;
1964325ba852SDmitry Baryshkov }
1965325ba852SDmitry Baryshkov
1966325ba852SDmitry Baryshkov /* DRM encoder functions */
1967325ba852SDmitry Baryshkov
tda998x_encoder_init(struct device * dev,struct drm_device * drm)1968325ba852SDmitry Baryshkov static int tda998x_encoder_init(struct device *dev, struct drm_device *drm)
1969325ba852SDmitry Baryshkov {
1970325ba852SDmitry Baryshkov struct tda998x_priv *priv = dev_get_drvdata(dev);
1971325ba852SDmitry Baryshkov u32 crtcs = 0;
1972325ba852SDmitry Baryshkov int ret;
1973325ba852SDmitry Baryshkov
1974325ba852SDmitry Baryshkov if (dev->of_node)
1975325ba852SDmitry Baryshkov crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
1976325ba852SDmitry Baryshkov
1977325ba852SDmitry Baryshkov /* If no CRTCs were found, fall back to our old behaviour */
1978325ba852SDmitry Baryshkov if (crtcs == 0) {
1979325ba852SDmitry Baryshkov dev_warn(dev, "Falling back to first CRTC\n");
1980325ba852SDmitry Baryshkov crtcs = 1 << 0;
1981325ba852SDmitry Baryshkov }
1982325ba852SDmitry Baryshkov
1983325ba852SDmitry Baryshkov priv->encoder.possible_crtcs = crtcs;
1984325ba852SDmitry Baryshkov
1985325ba852SDmitry Baryshkov ret = drm_simple_encoder_init(drm, &priv->encoder,
1986325ba852SDmitry Baryshkov DRM_MODE_ENCODER_TMDS);
1987325ba852SDmitry Baryshkov if (ret)
1988325ba852SDmitry Baryshkov goto err_encoder;
1989325ba852SDmitry Baryshkov
1990325ba852SDmitry Baryshkov ret = drm_bridge_attach(&priv->encoder, &priv->bridge, NULL, 0);
1991325ba852SDmitry Baryshkov if (ret)
1992325ba852SDmitry Baryshkov goto err_bridge;
1993325ba852SDmitry Baryshkov
1994325ba852SDmitry Baryshkov return 0;
1995325ba852SDmitry Baryshkov
1996325ba852SDmitry Baryshkov err_bridge:
1997325ba852SDmitry Baryshkov drm_encoder_cleanup(&priv->encoder);
1998325ba852SDmitry Baryshkov err_encoder:
1999325ba852SDmitry Baryshkov return ret;
2000325ba852SDmitry Baryshkov }
2001325ba852SDmitry Baryshkov
tda998x_bind(struct device * dev,struct device * master,void * data)2002325ba852SDmitry Baryshkov static int tda998x_bind(struct device *dev, struct device *master, void *data)
2003325ba852SDmitry Baryshkov {
2004325ba852SDmitry Baryshkov struct drm_device *drm = data;
2005325ba852SDmitry Baryshkov
2006325ba852SDmitry Baryshkov return tda998x_encoder_init(dev, drm);
2007325ba852SDmitry Baryshkov }
2008325ba852SDmitry Baryshkov
tda998x_unbind(struct device * dev,struct device * master,void * data)2009325ba852SDmitry Baryshkov static void tda998x_unbind(struct device *dev, struct device *master,
2010325ba852SDmitry Baryshkov void *data)
2011325ba852SDmitry Baryshkov {
2012325ba852SDmitry Baryshkov struct tda998x_priv *priv = dev_get_drvdata(dev);
2013325ba852SDmitry Baryshkov
2014325ba852SDmitry Baryshkov drm_encoder_cleanup(&priv->encoder);
2015325ba852SDmitry Baryshkov }
2016325ba852SDmitry Baryshkov
2017325ba852SDmitry Baryshkov static const struct component_ops tda998x_ops = {
2018325ba852SDmitry Baryshkov .bind = tda998x_bind,
2019325ba852SDmitry Baryshkov .unbind = tda998x_unbind,
2020325ba852SDmitry Baryshkov };
2021325ba852SDmitry Baryshkov
2022325ba852SDmitry Baryshkov static int
tda998x_probe(struct i2c_client * client)2023325ba852SDmitry Baryshkov tda998x_probe(struct i2c_client *client)
2024325ba852SDmitry Baryshkov {
2025325ba852SDmitry Baryshkov int ret;
2026325ba852SDmitry Baryshkov
2027325ba852SDmitry Baryshkov if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
2028325ba852SDmitry Baryshkov dev_warn(&client->dev, "adapter does not support I2C\n");
2029325ba852SDmitry Baryshkov return -EIO;
2030325ba852SDmitry Baryshkov }
2031325ba852SDmitry Baryshkov
2032325ba852SDmitry Baryshkov ret = tda998x_create(&client->dev);
2033325ba852SDmitry Baryshkov if (ret)
2034325ba852SDmitry Baryshkov return ret;
2035325ba852SDmitry Baryshkov
2036325ba852SDmitry Baryshkov ret = component_add(&client->dev, &tda998x_ops);
2037325ba852SDmitry Baryshkov if (ret)
2038325ba852SDmitry Baryshkov tda998x_destroy(&client->dev);
2039325ba852SDmitry Baryshkov return ret;
2040325ba852SDmitry Baryshkov }
2041325ba852SDmitry Baryshkov
tda998x_remove(struct i2c_client * client)2042325ba852SDmitry Baryshkov static void tda998x_remove(struct i2c_client *client)
2043325ba852SDmitry Baryshkov {
2044325ba852SDmitry Baryshkov component_del(&client->dev, &tda998x_ops);
2045325ba852SDmitry Baryshkov tda998x_destroy(&client->dev);
2046325ba852SDmitry Baryshkov }
2047325ba852SDmitry Baryshkov
2048325ba852SDmitry Baryshkov #ifdef CONFIG_OF
2049325ba852SDmitry Baryshkov static const struct of_device_id tda998x_dt_ids[] = {
2050325ba852SDmitry Baryshkov { .compatible = "nxp,tda998x", },
2051325ba852SDmitry Baryshkov { }
2052325ba852SDmitry Baryshkov };
2053325ba852SDmitry Baryshkov MODULE_DEVICE_TABLE(of, tda998x_dt_ids);
2054325ba852SDmitry Baryshkov #endif
2055325ba852SDmitry Baryshkov
2056325ba852SDmitry Baryshkov static const struct i2c_device_id tda998x_ids[] = {
2057325ba852SDmitry Baryshkov { "tda998x" },
2058325ba852SDmitry Baryshkov { }
2059325ba852SDmitry Baryshkov };
2060325ba852SDmitry Baryshkov MODULE_DEVICE_TABLE(i2c, tda998x_ids);
2061325ba852SDmitry Baryshkov
2062325ba852SDmitry Baryshkov static struct i2c_driver tda998x_driver = {
2063325ba852SDmitry Baryshkov .probe = tda998x_probe,
2064325ba852SDmitry Baryshkov .remove = tda998x_remove,
2065325ba852SDmitry Baryshkov .driver = {
2066325ba852SDmitry Baryshkov .name = "tda998x",
2067325ba852SDmitry Baryshkov .of_match_table = of_match_ptr(tda998x_dt_ids),
2068325ba852SDmitry Baryshkov },
2069325ba852SDmitry Baryshkov .id_table = tda998x_ids,
2070325ba852SDmitry Baryshkov };
2071325ba852SDmitry Baryshkov
2072325ba852SDmitry Baryshkov module_i2c_driver(tda998x_driver);
2073325ba852SDmitry Baryshkov
2074325ba852SDmitry Baryshkov MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
2075325ba852SDmitry Baryshkov MODULE_DESCRIPTION("NXP Semiconductors TDA998X HDMI Encoder");
2076325ba852SDmitry Baryshkov MODULE_LICENSE("GPL");
2077