blob: 80b94b51e06014f29ddec1e4d9fd34e99d61fcf9 [file] [log] [blame]
Rob Clarke7792ce2013-01-08 19:21:02 -06001/*
2 * Copyright (C) 2012 Texas Instruments
3 * Author: Rob Clark <robdclark@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18
19
Russell King893c3e52013-08-27 01:27:42 +010020#include <linux/hdmi.h>
Rob Clarke7792ce2013-01-08 19:21:02 -060021#include <linux/module.h>
Jean-Francois Moinef0b33b22014-01-25 18:14:39 +010022#include <sound/asoundef.h>
Rob Clarke7792ce2013-01-08 19:21:02 -060023
24#include <drm/drmP.h>
25#include <drm/drm_crtc_helper.h>
26#include <drm/drm_encoder_slave.h>
27#include <drm/drm_edid.h>
Russell Kingc4c11dd2013-08-14 21:43:30 +020028#include <drm/i2c/tda998x.h>
Rob Clarke7792ce2013-01-08 19:21:02 -060029
30#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
31
32struct tda998x_priv {
33 struct i2c_client *cec;
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +010034 struct i2c_client *hdmi;
Rob Clarke7792ce2013-01-08 19:21:02 -060035 uint16_t rev;
36 uint8_t current_page;
37 int dpms;
Russell Kingc4c11dd2013-08-14 21:43:30 +020038 bool is_hdmi_sink;
Russell King5e74c222013-08-14 21:43:29 +020039 u8 vip_cntrl_0;
40 u8 vip_cntrl_1;
41 u8 vip_cntrl_2;
Russell Kingc4c11dd2013-08-14 21:43:30 +020042 struct tda998x_encoder_params params;
Rob Clarke7792ce2013-01-08 19:21:02 -060043};
44
45#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv)
46
47/* The TDA9988 series of devices use a paged register scheme.. to simplify
48 * things we encode the page # in upper bits of the register #. To read/
49 * write a given register, we need to make sure CURPAGE register is set
50 * appropriately. Which implies reads/writes are not atomic. Fun!
51 */
52
53#define REG(page, addr) (((page) << 8) | (addr))
54#define REG2ADDR(reg) ((reg) & 0xff)
55#define REG2PAGE(reg) (((reg) >> 8) & 0xff)
56
57#define REG_CURPAGE 0xff /* write */
58
59
60/* Page 00h: General Control */
61#define REG_VERSION_LSB REG(0x00, 0x00) /* read */
62#define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */
63# define MAIN_CNTRL0_SR (1 << 0)
64# define MAIN_CNTRL0_DECS (1 << 1)
65# define MAIN_CNTRL0_DEHS (1 << 2)
66# define MAIN_CNTRL0_CECS (1 << 3)
67# define MAIN_CNTRL0_CEHS (1 << 4)
68# define MAIN_CNTRL0_SCALER (1 << 7)
69#define REG_VERSION_MSB REG(0x00, 0x02) /* read */
70#define REG_SOFTRESET REG(0x00, 0x0a) /* write */
71# define SOFTRESET_AUDIO (1 << 0)
72# define SOFTRESET_I2C_MASTER (1 << 1)
73#define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */
74#define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */
75#define REG_I2C_MASTER REG(0x00, 0x0d) /* read/write */
76# define I2C_MASTER_DIS_MM (1 << 0)
77# define I2C_MASTER_DIS_FILT (1 << 1)
78# define I2C_MASTER_APP_STRT_LAT (1 << 2)
Russell Kingc4c11dd2013-08-14 21:43:30 +020079#define REG_FEAT_POWERDOWN REG(0x00, 0x0e) /* read/write */
80# define FEAT_POWERDOWN_SPDIF (1 << 3)
Rob Clarke7792ce2013-01-08 19:21:02 -060081#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */
82#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */
83#define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */
84# define INT_FLAGS_2_EDID_BLK_RD (1 << 1)
Russell Kingc4c11dd2013-08-14 21:43:30 +020085#define REG_ENA_ACLK REG(0x00, 0x16) /* read/write */
Rob Clarke7792ce2013-01-08 19:21:02 -060086#define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */
87#define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */
88#define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */
89#define REG_ENA_AP REG(0x00, 0x1e) /* read/write */
90#define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */
91# define VIP_CNTRL_0_MIRR_A (1 << 7)
92# define VIP_CNTRL_0_SWAP_A(x) (((x) & 7) << 4)
93# define VIP_CNTRL_0_MIRR_B (1 << 3)
94# define VIP_CNTRL_0_SWAP_B(x) (((x) & 7) << 0)
95#define REG_VIP_CNTRL_1 REG(0x00, 0x21) /* write */
96# define VIP_CNTRL_1_MIRR_C (1 << 7)
97# define VIP_CNTRL_1_SWAP_C(x) (((x) & 7) << 4)
98# define VIP_CNTRL_1_MIRR_D (1 << 3)
99# define VIP_CNTRL_1_SWAP_D(x) (((x) & 7) << 0)
100#define REG_VIP_CNTRL_2 REG(0x00, 0x22) /* write */
101# define VIP_CNTRL_2_MIRR_E (1 << 7)
102# define VIP_CNTRL_2_SWAP_E(x) (((x) & 7) << 4)
103# define VIP_CNTRL_2_MIRR_F (1 << 3)
104# define VIP_CNTRL_2_SWAP_F(x) (((x) & 7) << 0)
105#define REG_VIP_CNTRL_3 REG(0x00, 0x23) /* write */
106# define VIP_CNTRL_3_X_TGL (1 << 0)
107# define VIP_CNTRL_3_H_TGL (1 << 1)
108# define VIP_CNTRL_3_V_TGL (1 << 2)
109# define VIP_CNTRL_3_EMB (1 << 3)
110# define VIP_CNTRL_3_SYNC_DE (1 << 4)
111# define VIP_CNTRL_3_SYNC_HS (1 << 5)
112# define VIP_CNTRL_3_DE_INT (1 << 6)
113# define VIP_CNTRL_3_EDGE (1 << 7)
114#define REG_VIP_CNTRL_4 REG(0x00, 0x24) /* write */
115# define VIP_CNTRL_4_BLC(x) (((x) & 3) << 0)
116# define VIP_CNTRL_4_BLANKIT(x) (((x) & 3) << 2)
117# define VIP_CNTRL_4_CCIR656 (1 << 4)
118# define VIP_CNTRL_4_656_ALT (1 << 5)
119# define VIP_CNTRL_4_TST_656 (1 << 6)
120# define VIP_CNTRL_4_TST_PAT (1 << 7)
121#define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */
122# define VIP_CNTRL_5_CKCASE (1 << 0)
123# define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1)
Russell Kingc4c11dd2013-08-14 21:43:30 +0200124#define REG_MUX_AP REG(0x00, 0x26) /* read/write */
Russell Kingbcb24812013-08-14 21:43:27 +0200125#define REG_MUX_VP_VIP_OUT REG(0x00, 0x27) /* read/write */
Rob Clarke7792ce2013-01-08 19:21:02 -0600126#define REG_MAT_CONTRL REG(0x00, 0x80) /* write */
127# define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0)
128# define MAT_CONTRL_MAT_BP (1 << 2)
129#define REG_VIDFORMAT REG(0x00, 0xa0) /* write */
130#define REG_REFPIX_MSB REG(0x00, 0xa1) /* write */
131#define REG_REFPIX_LSB REG(0x00, 0xa2) /* write */
132#define REG_REFLINE_MSB REG(0x00, 0xa3) /* write */
133#define REG_REFLINE_LSB REG(0x00, 0xa4) /* write */
134#define REG_NPIX_MSB REG(0x00, 0xa5) /* write */
135#define REG_NPIX_LSB REG(0x00, 0xa6) /* write */
136#define REG_NLINE_MSB REG(0x00, 0xa7) /* write */
137#define REG_NLINE_LSB REG(0x00, 0xa8) /* write */
138#define REG_VS_LINE_STRT_1_MSB REG(0x00, 0xa9) /* write */
139#define REG_VS_LINE_STRT_1_LSB REG(0x00, 0xaa) /* write */
140#define REG_VS_PIX_STRT_1_MSB REG(0x00, 0xab) /* write */
141#define REG_VS_PIX_STRT_1_LSB REG(0x00, 0xac) /* write */
142#define REG_VS_LINE_END_1_MSB REG(0x00, 0xad) /* write */
143#define REG_VS_LINE_END_1_LSB REG(0x00, 0xae) /* write */
144#define REG_VS_PIX_END_1_MSB REG(0x00, 0xaf) /* write */
145#define REG_VS_PIX_END_1_LSB REG(0x00, 0xb0) /* write */
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200146#define REG_VS_LINE_STRT_2_MSB REG(0x00, 0xb1) /* write */
147#define REG_VS_LINE_STRT_2_LSB REG(0x00, 0xb2) /* write */
Rob Clarke7792ce2013-01-08 19:21:02 -0600148#define REG_VS_PIX_STRT_2_MSB REG(0x00, 0xb3) /* write */
149#define REG_VS_PIX_STRT_2_LSB REG(0x00, 0xb4) /* write */
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200150#define REG_VS_LINE_END_2_MSB REG(0x00, 0xb5) /* write */
151#define REG_VS_LINE_END_2_LSB REG(0x00, 0xb6) /* write */
Rob Clarke7792ce2013-01-08 19:21:02 -0600152#define REG_VS_PIX_END_2_MSB REG(0x00, 0xb7) /* write */
153#define REG_VS_PIX_END_2_LSB REG(0x00, 0xb8) /* write */
154#define REG_HS_PIX_START_MSB REG(0x00, 0xb9) /* write */
155#define REG_HS_PIX_START_LSB REG(0x00, 0xba) /* write */
156#define REG_HS_PIX_STOP_MSB REG(0x00, 0xbb) /* write */
157#define REG_HS_PIX_STOP_LSB REG(0x00, 0xbc) /* write */
158#define REG_VWIN_START_1_MSB REG(0x00, 0xbd) /* write */
159#define REG_VWIN_START_1_LSB REG(0x00, 0xbe) /* write */
160#define REG_VWIN_END_1_MSB REG(0x00, 0xbf) /* write */
161#define REG_VWIN_END_1_LSB REG(0x00, 0xc0) /* write */
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200162#define REG_VWIN_START_2_MSB REG(0x00, 0xc1) /* write */
163#define REG_VWIN_START_2_LSB REG(0x00, 0xc2) /* write */
164#define REG_VWIN_END_2_MSB REG(0x00, 0xc3) /* write */
165#define REG_VWIN_END_2_LSB REG(0x00, 0xc4) /* write */
Rob Clarke7792ce2013-01-08 19:21:02 -0600166#define REG_DE_START_MSB REG(0x00, 0xc5) /* write */
167#define REG_DE_START_LSB REG(0x00, 0xc6) /* write */
168#define REG_DE_STOP_MSB REG(0x00, 0xc7) /* write */
169#define REG_DE_STOP_LSB REG(0x00, 0xc8) /* write */
170#define REG_TBG_CNTRL_0 REG(0x00, 0xca) /* write */
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200171# define TBG_CNTRL_0_TOP_TGL (1 << 0)
172# define TBG_CNTRL_0_TOP_SEL (1 << 1)
173# define TBG_CNTRL_0_DE_EXT (1 << 2)
174# define TBG_CNTRL_0_TOP_EXT (1 << 3)
Rob Clarke7792ce2013-01-08 19:21:02 -0600175# define TBG_CNTRL_0_FRAME_DIS (1 << 5)
176# define TBG_CNTRL_0_SYNC_MTHD (1 << 6)
177# define TBG_CNTRL_0_SYNC_ONCE (1 << 7)
178#define REG_TBG_CNTRL_1 REG(0x00, 0xcb) /* write */
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200179# define TBG_CNTRL_1_H_TGL (1 << 0)
180# define TBG_CNTRL_1_V_TGL (1 << 1)
181# define TBG_CNTRL_1_TGL_EN (1 << 2)
182# define TBG_CNTRL_1_X_EXT (1 << 3)
183# define TBG_CNTRL_1_H_EXT (1 << 4)
184# define TBG_CNTRL_1_V_EXT (1 << 5)
Rob Clarke7792ce2013-01-08 19:21:02 -0600185# define TBG_CNTRL_1_DWIN_DIS (1 << 6)
186#define REG_ENABLE_SPACE REG(0x00, 0xd6) /* write */
187#define REG_HVF_CNTRL_0 REG(0x00, 0xe4) /* write */
188# define HVF_CNTRL_0_SM (1 << 7)
189# define HVF_CNTRL_0_RWB (1 << 6)
190# define HVF_CNTRL_0_PREFIL(x) (((x) & 3) << 2)
191# define HVF_CNTRL_0_INTPOL(x) (((x) & 3) << 0)
192#define REG_HVF_CNTRL_1 REG(0x00, 0xe5) /* write */
193# define HVF_CNTRL_1_FOR (1 << 0)
194# define HVF_CNTRL_1_YUVBLK (1 << 1)
195# define HVF_CNTRL_1_VQR(x) (((x) & 3) << 2)
196# define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4)
197# define HVF_CNTRL_1_SEMI_PLANAR (1 << 6)
198#define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */
Russell Kingc4c11dd2013-08-14 21:43:30 +0200199#define REG_I2S_FORMAT REG(0x00, 0xfc) /* read/write */
200# define I2S_FORMAT(x) (((x) & 3) << 0)
201#define REG_AIP_CLKSEL REG(0x00, 0xfd) /* write */
202# define AIP_CLKSEL_FS(x) (((x) & 3) << 0)
203# define AIP_CLKSEL_CLK_POL(x) (((x) & 1) << 2)
204# define AIP_CLKSEL_AIP(x) (((x) & 7) << 3)
Rob Clarke7792ce2013-01-08 19:21:02 -0600205
206
207/* Page 02h: PLL settings */
208#define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */
209# define PLL_SERIAL_1_SRL_FDN (1 << 0)
210# define PLL_SERIAL_1_SRL_IZ(x) (((x) & 3) << 1)
211# define PLL_SERIAL_1_SRL_MAN_IZ (1 << 6)
212#define REG_PLL_SERIAL_2 REG(0x02, 0x01) /* read/write */
Jean-Francois Moine3ae471f2014-01-25 18:14:36 +0100213# define PLL_SERIAL_2_SRL_NOSC(x) ((x) << 0)
Rob Clarke7792ce2013-01-08 19:21:02 -0600214# define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4)
215#define REG_PLL_SERIAL_3 REG(0x02, 0x02) /* read/write */
216# define PLL_SERIAL_3_SRL_CCIR (1 << 0)
217# define PLL_SERIAL_3_SRL_DE (1 << 2)
218# define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4)
219#define REG_SERIALIZER REG(0x02, 0x03) /* read/write */
220#define REG_BUFFER_OUT REG(0x02, 0x04) /* read/write */
221#define REG_PLL_SCG1 REG(0x02, 0x05) /* read/write */
222#define REG_PLL_SCG2 REG(0x02, 0x06) /* read/write */
223#define REG_PLL_SCGN1 REG(0x02, 0x07) /* read/write */
224#define REG_PLL_SCGN2 REG(0x02, 0x08) /* read/write */
225#define REG_PLL_SCGR1 REG(0x02, 0x09) /* read/write */
226#define REG_PLL_SCGR2 REG(0x02, 0x0a) /* read/write */
227#define REG_AUDIO_DIV REG(0x02, 0x0e) /* read/write */
Russell Kingc4c11dd2013-08-14 21:43:30 +0200228# define AUDIO_DIV_SERCLK_1 0
229# define AUDIO_DIV_SERCLK_2 1
230# define AUDIO_DIV_SERCLK_4 2
231# define AUDIO_DIV_SERCLK_8 3
232# define AUDIO_DIV_SERCLK_16 4
233# define AUDIO_DIV_SERCLK_32 5
Rob Clarke7792ce2013-01-08 19:21:02 -0600234#define REG_SEL_CLK REG(0x02, 0x11) /* read/write */
235# define SEL_CLK_SEL_CLK1 (1 << 0)
236# define SEL_CLK_SEL_VRF_CLK(x) (((x) & 3) << 1)
237# define SEL_CLK_ENA_SC_CLK (1 << 3)
238#define REG_ANA_GENERAL REG(0x02, 0x12) /* read/write */
239
240
241/* Page 09h: EDID Control */
242#define REG_EDID_DATA_0 REG(0x09, 0x00) /* read */
243/* next 127 successive registers are the EDID block */
244#define REG_EDID_CTRL REG(0x09, 0xfa) /* read/write */
245#define REG_DDC_ADDR REG(0x09, 0xfb) /* read/write */
246#define REG_DDC_OFFS REG(0x09, 0xfc) /* read/write */
247#define REG_DDC_SEGM_ADDR REG(0x09, 0xfd) /* read/write */
248#define REG_DDC_SEGM REG(0x09, 0xfe) /* read/write */
249
250
251/* Page 10h: information frames and packets */
Russell Kingc4c11dd2013-08-14 21:43:30 +0200252#define REG_IF1_HB0 REG(0x10, 0x20) /* read/write */
253#define REG_IF2_HB0 REG(0x10, 0x40) /* read/write */
254#define REG_IF3_HB0 REG(0x10, 0x60) /* read/write */
255#define REG_IF4_HB0 REG(0x10, 0x80) /* read/write */
256#define REG_IF5_HB0 REG(0x10, 0xa0) /* read/write */
Rob Clarke7792ce2013-01-08 19:21:02 -0600257
258
259/* Page 11h: audio settings and content info packets */
260#define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */
261# define AIP_CNTRL_0_RST_FIFO (1 << 0)
262# define AIP_CNTRL_0_SWAP (1 << 1)
263# define AIP_CNTRL_0_LAYOUT (1 << 2)
264# define AIP_CNTRL_0_ACR_MAN (1 << 5)
265# define AIP_CNTRL_0_RST_CTS (1 << 6)
Russell Kingc4c11dd2013-08-14 21:43:30 +0200266#define REG_CA_I2S REG(0x11, 0x01) /* read/write */
267# define CA_I2S_CA_I2S(x) (((x) & 31) << 0)
268# define CA_I2S_HBR_CHSTAT (1 << 6)
269#define REG_LATENCY_RD REG(0x11, 0x04) /* read/write */
270#define REG_ACR_CTS_0 REG(0x11, 0x05) /* read/write */
271#define REG_ACR_CTS_1 REG(0x11, 0x06) /* read/write */
272#define REG_ACR_CTS_2 REG(0x11, 0x07) /* read/write */
273#define REG_ACR_N_0 REG(0x11, 0x08) /* read/write */
274#define REG_ACR_N_1 REG(0x11, 0x09) /* read/write */
275#define REG_ACR_N_2 REG(0x11, 0x0a) /* read/write */
276#define REG_CTS_N REG(0x11, 0x0c) /* read/write */
277# define CTS_N_K(x) (((x) & 7) << 0)
278# define CTS_N_M(x) (((x) & 3) << 4)
Rob Clarke7792ce2013-01-08 19:21:02 -0600279#define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */
280# define ENC_CNTRL_RST_ENC (1 << 0)
281# define ENC_CNTRL_RST_SEL (1 << 1)
282# define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2)
Russell Kingc4c11dd2013-08-14 21:43:30 +0200283#define REG_DIP_FLAGS REG(0x11, 0x0e) /* read/write */
284# define DIP_FLAGS_ACR (1 << 0)
285# define DIP_FLAGS_GC (1 << 1)
286#define REG_DIP_IF_FLAGS REG(0x11, 0x0f) /* read/write */
287# define DIP_IF_FLAGS_IF1 (1 << 1)
288# define DIP_IF_FLAGS_IF2 (1 << 2)
289# define DIP_IF_FLAGS_IF3 (1 << 3)
290# define DIP_IF_FLAGS_IF4 (1 << 4)
291# define DIP_IF_FLAGS_IF5 (1 << 5)
292#define REG_CH_STAT_B(x) REG(0x11, 0x14 + (x)) /* read/write */
Rob Clarke7792ce2013-01-08 19:21:02 -0600293
294
295/* Page 12h: HDCP and OTP */
296#define REG_TX3 REG(0x12, 0x9a) /* read/write */
Russell King063b4722013-08-14 21:43:26 +0200297#define REG_TX4 REG(0x12, 0x9b) /* read/write */
298# define TX4_PD_RAM (1 << 1)
Rob Clarke7792ce2013-01-08 19:21:02 -0600299#define REG_TX33 REG(0x12, 0xb8) /* read/write */
300# define TX33_HDMI (1 << 1)
301
302
303/* Page 13h: Gamut related metadata packets */
304
305
306
307/* CEC registers: (not paged)
308 */
309#define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */
310# define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7)
311# define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6)
312# define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1)
313# define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0)
314#define REG_CEC_RXSHPDLEV 0xfe /* read */
315# define CEC_RXSHPDLEV_RXSENS (1 << 0)
316# define CEC_RXSHPDLEV_HPD (1 << 1)
317
318#define REG_CEC_ENAMODS 0xff /* read/write */
319# define CEC_ENAMODS_DIS_FRO (1 << 6)
320# define CEC_ENAMODS_DIS_CCLK (1 << 5)
321# define CEC_ENAMODS_EN_RXSENS (1 << 2)
322# define CEC_ENAMODS_EN_HDMI (1 << 1)
323# define CEC_ENAMODS_EN_CEC (1 << 0)
324
325
326/* Device versions: */
327#define TDA9989N2 0x0101
328#define TDA19989 0x0201
329#define TDA19989N2 0x0202
330#define TDA19988 0x0301
331
332static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100333cec_write(struct tda998x_priv *priv, uint16_t addr, uint8_t val)
Rob Clarke7792ce2013-01-08 19:21:02 -0600334{
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100335 struct i2c_client *client = priv->cec;
Rob Clarke7792ce2013-01-08 19:21:02 -0600336 uint8_t buf[] = {addr, val};
337 int ret;
338
Jean-Francois Moine704d63f2014-01-25 18:14:46 +0100339 ret = i2c_master_send(client, buf, sizeof(buf));
Rob Clarke7792ce2013-01-08 19:21:02 -0600340 if (ret < 0)
341 dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ret, addr);
342}
343
344static uint8_t
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100345cec_read(struct tda998x_priv *priv, uint8_t addr)
Rob Clarke7792ce2013-01-08 19:21:02 -0600346{
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100347 struct i2c_client *client = priv->cec;
Rob Clarke7792ce2013-01-08 19:21:02 -0600348 uint8_t val;
349 int ret;
350
351 ret = i2c_master_send(client, &addr, sizeof(addr));
352 if (ret < 0)
353 goto fail;
354
355 ret = i2c_master_recv(client, &val, sizeof(val));
356 if (ret < 0)
357 goto fail;
358
359 return val;
360
361fail:
362 dev_err(&client->dev, "Error %d reading from cec:0x%x\n", ret, addr);
363 return 0;
364}
365
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100366static int
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100367set_page(struct tda998x_priv *priv, uint16_t reg)
Rob Clarke7792ce2013-01-08 19:21:02 -0600368{
Rob Clarke7792ce2013-01-08 19:21:02 -0600369 if (REG2PAGE(reg) != priv->current_page) {
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100370 struct i2c_client *client = priv->hdmi;
Rob Clarke7792ce2013-01-08 19:21:02 -0600371 uint8_t buf[] = {
372 REG_CURPAGE, REG2PAGE(reg)
373 };
374 int ret = i2c_master_send(client, buf, sizeof(buf));
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100375 if (ret < 0) {
Jean-Francois Moine704d63f2014-01-25 18:14:46 +0100376 dev_err(&client->dev, "setpage %04x err %d\n",
377 reg, ret);
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100378 return ret;
379 }
Rob Clarke7792ce2013-01-08 19:21:02 -0600380
381 priv->current_page = REG2PAGE(reg);
382 }
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100383 return 0;
Rob Clarke7792ce2013-01-08 19:21:02 -0600384}
385
386static int
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100387reg_read_range(struct tda998x_priv *priv, uint16_t reg, char *buf, int cnt)
Rob Clarke7792ce2013-01-08 19:21:02 -0600388{
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100389 struct i2c_client *client = priv->hdmi;
Rob Clarke7792ce2013-01-08 19:21:02 -0600390 uint8_t addr = REG2ADDR(reg);
391 int ret;
392
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100393 ret = set_page(priv, reg);
394 if (ret < 0)
395 return ret;
Rob Clarke7792ce2013-01-08 19:21:02 -0600396
397 ret = i2c_master_send(client, &addr, sizeof(addr));
398 if (ret < 0)
399 goto fail;
400
401 ret = i2c_master_recv(client, buf, cnt);
402 if (ret < 0)
403 goto fail;
404
405 return ret;
406
407fail:
408 dev_err(&client->dev, "Error %d reading from 0x%x\n", ret, reg);
409 return ret;
410}
411
Russell Kingc4c11dd2013-08-14 21:43:30 +0200412static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100413reg_write_range(struct tda998x_priv *priv, uint16_t reg, uint8_t *p, int cnt)
Russell Kingc4c11dd2013-08-14 21:43:30 +0200414{
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100415 struct i2c_client *client = priv->hdmi;
Russell Kingc4c11dd2013-08-14 21:43:30 +0200416 uint8_t buf[cnt+1];
417 int ret;
418
419 buf[0] = REG2ADDR(reg);
420 memcpy(&buf[1], p, cnt);
421
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100422 ret = set_page(priv, reg);
423 if (ret < 0)
424 return;
Russell Kingc4c11dd2013-08-14 21:43:30 +0200425
426 ret = i2c_master_send(client, buf, cnt + 1);
427 if (ret < 0)
428 dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
429}
430
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100431static int
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100432reg_read(struct tda998x_priv *priv, uint16_t reg)
Rob Clarke7792ce2013-01-08 19:21:02 -0600433{
434 uint8_t val = 0;
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100435 int ret;
436
437 ret = reg_read_range(priv, reg, &val, sizeof(val));
438 if (ret < 0)
439 return ret;
Rob Clarke7792ce2013-01-08 19:21:02 -0600440 return val;
441}
442
443static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100444reg_write(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
Rob Clarke7792ce2013-01-08 19:21:02 -0600445{
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100446 struct i2c_client *client = priv->hdmi;
Rob Clarke7792ce2013-01-08 19:21:02 -0600447 uint8_t buf[] = {REG2ADDR(reg), val};
448 int ret;
449
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100450 ret = set_page(priv, reg);
451 if (ret < 0)
452 return;
Rob Clarke7792ce2013-01-08 19:21:02 -0600453
Jean-Francois Moine704d63f2014-01-25 18:14:46 +0100454 ret = i2c_master_send(client, buf, sizeof(buf));
Rob Clarke7792ce2013-01-08 19:21:02 -0600455 if (ret < 0)
456 dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
457}
458
459static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100460reg_write16(struct tda998x_priv *priv, uint16_t reg, uint16_t val)
Rob Clarke7792ce2013-01-08 19:21:02 -0600461{
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100462 struct i2c_client *client = priv->hdmi;
Rob Clarke7792ce2013-01-08 19:21:02 -0600463 uint8_t buf[] = {REG2ADDR(reg), val >> 8, val};
464 int ret;
465
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100466 ret = set_page(priv, reg);
467 if (ret < 0)
468 return;
Rob Clarke7792ce2013-01-08 19:21:02 -0600469
Jean-Francois Moine704d63f2014-01-25 18:14:46 +0100470 ret = i2c_master_send(client, buf, sizeof(buf));
Rob Clarke7792ce2013-01-08 19:21:02 -0600471 if (ret < 0)
472 dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg);
473}
474
475static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100476reg_set(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
Rob Clarke7792ce2013-01-08 19:21:02 -0600477{
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100478 int old_val;
479
480 old_val = reg_read(priv, reg);
481 if (old_val >= 0)
482 reg_write(priv, reg, old_val | val);
Rob Clarke7792ce2013-01-08 19:21:02 -0600483}
484
485static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100486reg_clear(struct tda998x_priv *priv, uint16_t reg, uint8_t val)
Rob Clarke7792ce2013-01-08 19:21:02 -0600487{
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +0100488 int old_val;
489
490 old_val = reg_read(priv, reg);
491 if (old_val >= 0)
492 reg_write(priv, reg, old_val & ~val);
Rob Clarke7792ce2013-01-08 19:21:02 -0600493}
494
495static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100496tda998x_reset(struct tda998x_priv *priv)
Rob Clarke7792ce2013-01-08 19:21:02 -0600497{
498 /* reset audio and i2c master: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100499 reg_set(priv, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
Rob Clarke7792ce2013-01-08 19:21:02 -0600500 msleep(50);
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100501 reg_clear(priv, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER);
Rob Clarke7792ce2013-01-08 19:21:02 -0600502 msleep(50);
503
504 /* reset transmitter: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100505 reg_set(priv, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
506 reg_clear(priv, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR);
Rob Clarke7792ce2013-01-08 19:21:02 -0600507
508 /* PLL registers common configuration */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100509 reg_write(priv, REG_PLL_SERIAL_1, 0x00);
510 reg_write(priv, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1));
511 reg_write(priv, REG_PLL_SERIAL_3, 0x00);
512 reg_write(priv, REG_SERIALIZER, 0x00);
513 reg_write(priv, REG_BUFFER_OUT, 0x00);
514 reg_write(priv, REG_PLL_SCG1, 0x00);
515 reg_write(priv, REG_AUDIO_DIV, AUDIO_DIV_SERCLK_8);
516 reg_write(priv, REG_SEL_CLK, SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
517 reg_write(priv, REG_PLL_SCGN1, 0xfa);
518 reg_write(priv, REG_PLL_SCGN2, 0x00);
519 reg_write(priv, REG_PLL_SCGR1, 0x5b);
520 reg_write(priv, REG_PLL_SCGR2, 0x00);
521 reg_write(priv, REG_PLL_SCG2, 0x10);
Russell Kingbcb24812013-08-14 21:43:27 +0200522
523 /* Write the default value MUX register */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100524 reg_write(priv, REG_MUX_VP_VIP_OUT, 0x24);
Rob Clarke7792ce2013-01-08 19:21:02 -0600525}
526
Russell Kingc4c11dd2013-08-14 21:43:30 +0200527static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes)
528{
529 uint8_t sum = 0;
530
531 while (bytes--)
532 sum += *buf++;
533 return (255 - sum) + 1;
534}
535
536#define HB(x) (x)
537#define PB(x) (HB(2) + 1 + (x))
538
539static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100540tda998x_write_if(struct tda998x_priv *priv, uint8_t bit, uint16_t addr,
Russell Kingc4c11dd2013-08-14 21:43:30 +0200541 uint8_t *buf, size_t size)
542{
543 buf[PB(0)] = tda998x_cksum(buf, size);
544
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100545 reg_clear(priv, REG_DIP_IF_FLAGS, bit);
546 reg_write_range(priv, addr, buf, size);
547 reg_set(priv, REG_DIP_IF_FLAGS, bit);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200548}
549
550static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100551tda998x_write_aif(struct tda998x_priv *priv, struct tda998x_encoder_params *p)
Russell Kingc4c11dd2013-08-14 21:43:30 +0200552{
Jean-Francois Moine9e541462014-01-25 18:14:41 +0100553 u8 buf[PB(HDMI_AUDIO_INFOFRAME_SIZE) + 1];
Russell Kingc4c11dd2013-08-14 21:43:30 +0200554
Jean-Francois Moine7288ca02014-01-25 18:14:44 +0100555 memset(buf, 0, sizeof(buf));
Jean-Francois Moine9e541462014-01-25 18:14:41 +0100556 buf[HB(0)] = HDMI_INFOFRAME_TYPE_AUDIO;
Russell Kingc4c11dd2013-08-14 21:43:30 +0200557 buf[HB(1)] = 0x01;
Jean-Francois Moine9e541462014-01-25 18:14:41 +0100558 buf[HB(2)] = HDMI_AUDIO_INFOFRAME_SIZE;
Russell Kingc4c11dd2013-08-14 21:43:30 +0200559 buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */
560 buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */
561 buf[PB(4)] = p->audio_frame[4];
562 buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */
563
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100564 tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf,
Russell Kingc4c11dd2013-08-14 21:43:30 +0200565 sizeof(buf));
566}
567
568static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100569tda998x_write_avi(struct tda998x_priv *priv, struct drm_display_mode *mode)
Russell Kingc4c11dd2013-08-14 21:43:30 +0200570{
Jean-Francois Moine9e541462014-01-25 18:14:41 +0100571 u8 buf[PB(HDMI_AVI_INFOFRAME_SIZE) + 1];
Russell Kingc4c11dd2013-08-14 21:43:30 +0200572
573 memset(buf, 0, sizeof(buf));
Jean-Francois Moine9e541462014-01-25 18:14:41 +0100574 buf[HB(0)] = HDMI_INFOFRAME_TYPE_AVI;
Russell Kingc4c11dd2013-08-14 21:43:30 +0200575 buf[HB(1)] = 0x02;
Jean-Francois Moine9e541462014-01-25 18:14:41 +0100576 buf[HB(2)] = HDMI_AVI_INFOFRAME_SIZE;
Russell King893c3e52013-08-27 01:27:42 +0100577 buf[PB(1)] = HDMI_SCAN_MODE_UNDERSCAN;
Jean-Francois Moinebdf63452014-01-25 18:14:40 +0100578 buf[PB(2)] = HDMI_ACTIVE_ASPECT_PICTURE;
Russell King893c3e52013-08-27 01:27:42 +0100579 buf[PB(3)] = HDMI_QUANTIZATION_RANGE_FULL << 2;
Russell Kingc4c11dd2013-08-14 21:43:30 +0200580 buf[PB(4)] = drm_match_cea_mode(mode);
581
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100582 tda998x_write_if(priv, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf,
Russell Kingc4c11dd2013-08-14 21:43:30 +0200583 sizeof(buf));
584}
585
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100586static void tda998x_audio_mute(struct tda998x_priv *priv, bool on)
Russell Kingc4c11dd2013-08-14 21:43:30 +0200587{
588 if (on) {
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100589 reg_set(priv, REG_SOFTRESET, SOFTRESET_AUDIO);
590 reg_clear(priv, REG_SOFTRESET, SOFTRESET_AUDIO);
591 reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200592 } else {
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100593 reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200594 }
595}
596
597static void
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100598tda998x_configure_audio(struct tda998x_priv *priv,
Russell Kingc4c11dd2013-08-14 21:43:30 +0200599 struct drm_display_mode *mode, struct tda998x_encoder_params *p)
600{
601 uint8_t buf[6], clksel_aip, clksel_fs, ca_i2s, cts_n, adiv;
602 uint32_t n;
603
604 /* Enable audio ports */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100605 reg_write(priv, REG_ENA_AP, p->audio_cfg);
606 reg_write(priv, REG_ENA_ACLK, p->audio_clk_cfg);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200607
608 /* Set audio input source */
609 switch (p->audio_format) {
610 case AFMT_SPDIF:
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100611 reg_write(priv, REG_MUX_AP, 0x40);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200612 clksel_aip = AIP_CLKSEL_AIP(0);
613 /* FS64SPDIF */
614 clksel_fs = AIP_CLKSEL_FS(2);
615 cts_n = CTS_N_M(3) | CTS_N_K(3);
616 ca_i2s = 0;
617 break;
618
619 case AFMT_I2S:
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100620 reg_write(priv, REG_MUX_AP, 0x64);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200621 clksel_aip = AIP_CLKSEL_AIP(1);
622 /* ACLK */
623 clksel_fs = AIP_CLKSEL_FS(0);
624 cts_n = CTS_N_M(3) | CTS_N_K(3);
625 ca_i2s = CA_I2S_CA_I2S(0);
626 break;
David Herrmann3b288022013-09-01 15:23:04 +0200627
628 default:
629 BUG();
630 return;
Russell Kingc4c11dd2013-08-14 21:43:30 +0200631 }
632
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100633 reg_write(priv, REG_AIP_CLKSEL, clksel_aip);
634 reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200635
636 /* Enable automatic CTS generation */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100637 reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_ACR_MAN);
638 reg_write(priv, REG_CTS_N, cts_n);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200639
640 /*
641 * Audio input somehow depends on HDMI line rate which is
642 * related to pixclk. Testing showed that modes with pixclk
643 * >100MHz need a larger divider while <40MHz need the default.
644 * There is no detailed info in the datasheet, so we just
645 * assume 100MHz requires larger divider.
646 */
647 if (mode->clock > 100000)
648 adiv = AUDIO_DIV_SERCLK_16;
649 else
650 adiv = AUDIO_DIV_SERCLK_8;
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100651 reg_write(priv, REG_AUDIO_DIV, adiv);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200652
653 /*
654 * This is the approximate value of N, which happens to be
655 * the recommended values for non-coherent clocks.
656 */
657 n = 128 * p->audio_sample_rate / 1000;
658
659 /* Write the CTS and N values */
660 buf[0] = 0x44;
661 buf[1] = 0x42;
662 buf[2] = 0x01;
663 buf[3] = n;
664 buf[4] = n >> 8;
665 buf[5] = n >> 16;
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100666 reg_write_range(priv, REG_ACR_CTS_0, buf, 6);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200667
668 /* Set CTS clock reference */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100669 reg_write(priv, REG_AIP_CLKSEL, clksel_aip | clksel_fs);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200670
671 /* Reset CTS generator */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100672 reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
673 reg_clear(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200674
675 /* Write the channel status */
Jean-Francois Moinef0b33b22014-01-25 18:14:39 +0100676 buf[0] = IEC958_AES0_CON_NOT_COPYRIGHT;
Russell Kingc4c11dd2013-08-14 21:43:30 +0200677 buf[1] = 0x00;
Jean-Francois Moinef0b33b22014-01-25 18:14:39 +0100678 buf[2] = IEC958_AES3_CON_FS_NOTID;
679 buf[3] = IEC958_AES4_CON_ORIGFS_NOTID |
680 IEC958_AES4_CON_MAX_WORDLEN_24;
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100681 reg_write_range(priv, REG_CH_STAT_B(0), buf, 4);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200682
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100683 tda998x_audio_mute(priv, true);
Jean-Francois Moine73d5e252014-01-25 18:14:44 +0100684 msleep(20);
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100685 tda998x_audio_mute(priv, false);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200686
687 /* Write the audio information packet */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100688 tda998x_write_aif(priv, p);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200689}
690
Rob Clarke7792ce2013-01-08 19:21:02 -0600691/* DRM encoder functions */
692
693static void
694tda998x_encoder_set_config(struct drm_encoder *encoder, void *params)
695{
Russell Kingc4c11dd2013-08-14 21:43:30 +0200696 struct tda998x_priv *priv = to_tda998x_priv(encoder);
697 struct tda998x_encoder_params *p = params;
698
699 priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
700 (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
701 VIP_CNTRL_0_SWAP_B(p->swap_b) |
702 (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
703 priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
704 (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
705 VIP_CNTRL_1_SWAP_D(p->swap_d) |
706 (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
707 priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
708 (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
709 VIP_CNTRL_2_SWAP_F(p->swap_f) |
710 (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
711
712 priv->params = *p;
Rob Clarke7792ce2013-01-08 19:21:02 -0600713}
714
715static void
716tda998x_encoder_dpms(struct drm_encoder *encoder, int mode)
717{
718 struct tda998x_priv *priv = to_tda998x_priv(encoder);
719
720 /* we only care about on or off: */
721 if (mode != DRM_MODE_DPMS_ON)
722 mode = DRM_MODE_DPMS_OFF;
723
724 if (mode == priv->dpms)
725 return;
726
727 switch (mode) {
728 case DRM_MODE_DPMS_ON:
Russell Kingc4c11dd2013-08-14 21:43:30 +0200729 /* enable video ports, audio will be enabled later */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100730 reg_write(priv, REG_ENA_VP_0, 0xff);
731 reg_write(priv, REG_ENA_VP_1, 0xff);
732 reg_write(priv, REG_ENA_VP_2, 0xff);
Rob Clarke7792ce2013-01-08 19:21:02 -0600733 /* set muxing after enabling ports: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100734 reg_write(priv, REG_VIP_CNTRL_0, priv->vip_cntrl_0);
735 reg_write(priv, REG_VIP_CNTRL_1, priv->vip_cntrl_1);
736 reg_write(priv, REG_VIP_CNTRL_2, priv->vip_cntrl_2);
Rob Clarke7792ce2013-01-08 19:21:02 -0600737 break;
738 case DRM_MODE_DPMS_OFF:
Russell Kingdb6aaf42013-09-24 10:37:13 +0100739 /* disable video ports */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100740 reg_write(priv, REG_ENA_VP_0, 0x00);
741 reg_write(priv, REG_ENA_VP_1, 0x00);
742 reg_write(priv, REG_ENA_VP_2, 0x00);
Rob Clarke7792ce2013-01-08 19:21:02 -0600743 break;
744 }
745
746 priv->dpms = mode;
747}
748
749static void
750tda998x_encoder_save(struct drm_encoder *encoder)
751{
752 DBG("");
753}
754
755static void
756tda998x_encoder_restore(struct drm_encoder *encoder)
757{
758 DBG("");
759}
760
761static bool
762tda998x_encoder_mode_fixup(struct drm_encoder *encoder,
763 const struct drm_display_mode *mode,
764 struct drm_display_mode *adjusted_mode)
765{
766 return true;
767}
768
769static int
770tda998x_encoder_mode_valid(struct drm_encoder *encoder,
771 struct drm_display_mode *mode)
772{
773 return MODE_OK;
774}
775
776static void
777tda998x_encoder_mode_set(struct drm_encoder *encoder,
778 struct drm_display_mode *mode,
779 struct drm_display_mode *adjusted_mode)
780{
781 struct tda998x_priv *priv = to_tda998x_priv(encoder);
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200782 uint16_t ref_pix, ref_line, n_pix, n_line;
783 uint16_t hs_pix_s, hs_pix_e;
784 uint16_t vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e;
785 uint16_t vs2_pix_s, vs2_pix_e, vs2_line_s, vs2_line_e;
786 uint16_t vwin1_line_s, vwin1_line_e;
787 uint16_t vwin2_line_s, vwin2_line_e;
788 uint16_t de_pix_s, de_pix_e;
Rob Clarke7792ce2013-01-08 19:21:02 -0600789 uint8_t reg, div, rep;
790
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200791 /*
792 * Internally TDA998x is using ITU-R BT.656 style sync but
793 * we get VESA style sync. TDA998x is using a reference pixel
794 * relative to ITU to sync to the input frame and for output
795 * sync generation. Currently, we are using reference detection
796 * from HS/VS, i.e. REFPIX/REFLINE denote frame start sync point
797 * which is position of rising VS with coincident rising HS.
798 *
799 * Now there is some issues to take care of:
800 * - HDMI data islands require sync-before-active
801 * - TDA998x register values must be > 0 to be enabled
802 * - REFLINE needs an additional offset of +1
803 * - REFPIX needs an addtional offset of +1 for UYUV and +3 for RGB
804 *
805 * So we add +1 to all horizontal and vertical register values,
806 * plus an additional +3 for REFPIX as we are using RGB input only.
Rob Clarke7792ce2013-01-08 19:21:02 -0600807 */
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200808 n_pix = mode->htotal;
809 n_line = mode->vtotal;
Rob Clarke7792ce2013-01-08 19:21:02 -0600810
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200811 hs_pix_e = mode->hsync_end - mode->hdisplay;
812 hs_pix_s = mode->hsync_start - mode->hdisplay;
813 de_pix_e = mode->htotal;
814 de_pix_s = mode->htotal - mode->hdisplay;
815 ref_pix = 3 + hs_pix_s;
816
Sebastian Hesselbarth179f1aa2013-08-14 21:43:32 +0200817 /*
818 * Attached LCD controllers may generate broken sync. Allow
819 * those to adjust the position of the rising VS edge by adding
820 * HSKEW to ref_pix.
821 */
822 if (adjusted_mode->flags & DRM_MODE_FLAG_HSKEW)
823 ref_pix += adjusted_mode->hskew;
824
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200825 if ((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) {
826 ref_line = 1 + mode->vsync_start - mode->vdisplay;
827 vwin1_line_s = mode->vtotal - mode->vdisplay - 1;
828 vwin1_line_e = vwin1_line_s + mode->vdisplay;
829 vs1_pix_s = vs1_pix_e = hs_pix_s;
830 vs1_line_s = mode->vsync_start - mode->vdisplay;
831 vs1_line_e = vs1_line_s +
832 mode->vsync_end - mode->vsync_start;
833 vwin2_line_s = vwin2_line_e = 0;
834 vs2_pix_s = vs2_pix_e = 0;
835 vs2_line_s = vs2_line_e = 0;
836 } else {
837 ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2;
838 vwin1_line_s = (mode->vtotal - mode->vdisplay)/2;
839 vwin1_line_e = vwin1_line_s + mode->vdisplay/2;
840 vs1_pix_s = vs1_pix_e = hs_pix_s;
841 vs1_line_s = (mode->vsync_start - mode->vdisplay)/2;
842 vs1_line_e = vs1_line_s +
843 (mode->vsync_end - mode->vsync_start)/2;
844 vwin2_line_s = vwin1_line_s + mode->vtotal/2;
845 vwin2_line_e = vwin2_line_s + mode->vdisplay/2;
846 vs2_pix_s = vs2_pix_e = hs_pix_s + mode->htotal/2;
847 vs2_line_s = vs1_line_s + mode->vtotal/2 ;
848 vs2_line_e = vs2_line_s +
849 (mode->vsync_end - mode->vsync_start)/2;
850 }
Rob Clarke7792ce2013-01-08 19:21:02 -0600851
852 div = 148500 / mode->clock;
Jean-Francois Moine3ae471f2014-01-25 18:14:36 +0100853 if (div != 0) {
854 div--;
855 if (div > 3)
856 div = 3;
857 }
Rob Clarke7792ce2013-01-08 19:21:02 -0600858
Rob Clarke7792ce2013-01-08 19:21:02 -0600859 /* mute the audio FIFO: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100860 reg_set(priv, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO);
Rob Clarke7792ce2013-01-08 19:21:02 -0600861
862 /* set HDMI HDCP mode off: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100863 reg_set(priv, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
864 reg_clear(priv, REG_TX33, TX33_HDMI);
865 reg_write(priv, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0));
Rob Clarke7792ce2013-01-08 19:21:02 -0600866
Rob Clarke7792ce2013-01-08 19:21:02 -0600867 /* no pre-filter or interpolator: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100868 reg_write(priv, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) |
Rob Clarke7792ce2013-01-08 19:21:02 -0600869 HVF_CNTRL_0_INTPOL(0));
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100870 reg_write(priv, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0));
871 reg_write(priv, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) |
Rob Clarke7792ce2013-01-08 19:21:02 -0600872 VIP_CNTRL_4_BLC(0));
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100873 reg_clear(priv, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR);
Rob Clarke7792ce2013-01-08 19:21:02 -0600874
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100875 reg_clear(priv, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ);
876 reg_clear(priv, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE);
877 reg_write(priv, REG_SERIALIZER, 0);
878 reg_write(priv, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0));
Rob Clarke7792ce2013-01-08 19:21:02 -0600879
880 /* TODO enable pixel repeat for pixel rates less than 25Msamp/s */
881 rep = 0;
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100882 reg_write(priv, REG_RPT_CNTRL, 0);
883 reg_write(priv, REG_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) |
Rob Clarke7792ce2013-01-08 19:21:02 -0600884 SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK);
885
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100886 reg_write(priv, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) |
Rob Clarke7792ce2013-01-08 19:21:02 -0600887 PLL_SERIAL_2_SRL_PR(rep));
888
Rob Clarke7792ce2013-01-08 19:21:02 -0600889 /* set color matrix bypass flag: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100890 reg_set(priv, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP);
Rob Clarke7792ce2013-01-08 19:21:02 -0600891
892 /* set BIAS tmds value: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100893 reg_write(priv, REG_ANA_GENERAL, 0x09);
Rob Clarke7792ce2013-01-08 19:21:02 -0600894
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100895 reg_clear(priv, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD);
Rob Clarke7792ce2013-01-08 19:21:02 -0600896
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200897 /*
898 * Sync on rising HSYNC/VSYNC
899 */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100900 reg_write(priv, REG_VIP_CNTRL_3, 0);
901 reg_set(priv, REG_VIP_CNTRL_3, VIP_CNTRL_3_SYNC_HS);
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200902
903 /*
904 * TDA19988 requires high-active sync at input stage,
905 * so invert low-active sync provided by master encoder here
906 */
907 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100908 reg_set(priv, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL);
Rob Clarke7792ce2013-01-08 19:21:02 -0600909 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100910 reg_set(priv, REG_VIP_CNTRL_3, VIP_CNTRL_3_V_TGL);
Rob Clarke7792ce2013-01-08 19:21:02 -0600911
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200912 /*
913 * Always generate sync polarity relative to input sync and
914 * revert input stage toggled sync at output stage
915 */
916 reg = TBG_CNTRL_1_TGL_EN;
Rob Clarke7792ce2013-01-08 19:21:02 -0600917 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
Sebastian Hesselbarth088d61d2013-08-14 21:43:31 +0200918 reg |= TBG_CNTRL_1_H_TGL;
919 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
920 reg |= TBG_CNTRL_1_V_TGL;
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100921 reg_write(priv, REG_TBG_CNTRL_1, reg);
Rob Clarke7792ce2013-01-08 19:21:02 -0600922
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100923 reg_write(priv, REG_VIDFORMAT, 0x00);
924 reg_write16(priv, REG_REFPIX_MSB, ref_pix);
925 reg_write16(priv, REG_REFLINE_MSB, ref_line);
926 reg_write16(priv, REG_NPIX_MSB, n_pix);
927 reg_write16(priv, REG_NLINE_MSB, n_line);
928 reg_write16(priv, REG_VS_LINE_STRT_1_MSB, vs1_line_s);
929 reg_write16(priv, REG_VS_PIX_STRT_1_MSB, vs1_pix_s);
930 reg_write16(priv, REG_VS_LINE_END_1_MSB, vs1_line_e);
931 reg_write16(priv, REG_VS_PIX_END_1_MSB, vs1_pix_e);
932 reg_write16(priv, REG_VS_LINE_STRT_2_MSB, vs2_line_s);
933 reg_write16(priv, REG_VS_PIX_STRT_2_MSB, vs2_pix_s);
934 reg_write16(priv, REG_VS_LINE_END_2_MSB, vs2_line_e);
935 reg_write16(priv, REG_VS_PIX_END_2_MSB, vs2_pix_e);
936 reg_write16(priv, REG_HS_PIX_START_MSB, hs_pix_s);
937 reg_write16(priv, REG_HS_PIX_STOP_MSB, hs_pix_e);
938 reg_write16(priv, REG_VWIN_START_1_MSB, vwin1_line_s);
939 reg_write16(priv, REG_VWIN_END_1_MSB, vwin1_line_e);
940 reg_write16(priv, REG_VWIN_START_2_MSB, vwin2_line_s);
941 reg_write16(priv, REG_VWIN_END_2_MSB, vwin2_line_e);
942 reg_write16(priv, REG_DE_START_MSB, de_pix_s);
943 reg_write16(priv, REG_DE_STOP_MSB, de_pix_e);
Rob Clarke7792ce2013-01-08 19:21:02 -0600944
945 if (priv->rev == TDA19988) {
946 /* let incoming pixels fill the active space (if any) */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100947 reg_write(priv, REG_ENABLE_SPACE, 0x00);
Rob Clarke7792ce2013-01-08 19:21:02 -0600948 }
949
Rob Clarke7792ce2013-01-08 19:21:02 -0600950 /* must be last register set: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100951 reg_clear(priv, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200952
953 /* Only setup the info frames if the sink is HDMI */
954 if (priv->is_hdmi_sink) {
955 /* We need to turn HDMI HDCP stuff on to get audio through */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100956 reg_clear(priv, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS);
957 reg_write(priv, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(1));
958 reg_set(priv, REG_TX33, TX33_HDMI);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200959
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100960 tda998x_write_avi(priv, adjusted_mode);
Russell Kingc4c11dd2013-08-14 21:43:30 +0200961
962 if (priv->params.audio_cfg)
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100963 tda998x_configure_audio(priv, adjusted_mode,
Russell Kingc4c11dd2013-08-14 21:43:30 +0200964 &priv->params);
965 }
Rob Clarke7792ce2013-01-08 19:21:02 -0600966}
967
968static enum drm_connector_status
969tda998x_encoder_detect(struct drm_encoder *encoder,
970 struct drm_connector *connector)
971{
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100972 struct tda998x_priv *priv = to_tda998x_priv(encoder);
973 uint8_t val = cec_read(priv, REG_CEC_RXSHPDLEV);
974
Rob Clarke7792ce2013-01-08 19:21:02 -0600975 return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected :
976 connector_status_disconnected;
977}
978
979static int
980read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk)
981{
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100982 struct tda998x_priv *priv = to_tda998x_priv(encoder);
Rob Clarke7792ce2013-01-08 19:21:02 -0600983 uint8_t offset, segptr;
984 int ret, i;
985
986 /* enable EDID read irq: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100987 reg_set(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
Rob Clarke7792ce2013-01-08 19:21:02 -0600988
989 offset = (blk & 1) ? 128 : 0;
990 segptr = blk / 2;
991
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100992 reg_write(priv, REG_DDC_ADDR, 0xa0);
993 reg_write(priv, REG_DDC_OFFS, offset);
994 reg_write(priv, REG_DDC_SEGM_ADDR, 0x60);
995 reg_write(priv, REG_DDC_SEGM, segptr);
Rob Clarke7792ce2013-01-08 19:21:02 -0600996
997 /* enable reading EDID: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +0100998 reg_write(priv, REG_EDID_CTRL, 0x1);
Rob Clarke7792ce2013-01-08 19:21:02 -0600999
1000 /* flag must be cleared by sw: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001001 reg_write(priv, REG_EDID_CTRL, 0x0);
Rob Clarke7792ce2013-01-08 19:21:02 -06001002
1003 /* wait for block read to complete: */
1004 for (i = 100; i > 0; i--) {
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +01001005 ret = reg_read(priv, REG_INT_FLAGS_2);
1006 if (ret < 0)
1007 return ret;
1008 if (ret & INT_FLAGS_2_EDID_BLK_RD)
Rob Clarke7792ce2013-01-08 19:21:02 -06001009 break;
1010 msleep(1);
1011 }
1012
1013 if (i == 0)
1014 return -ETIMEDOUT;
1015
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001016 ret = reg_read_range(priv, REG_EDID_DATA_0, buf, EDID_LENGTH);
Rob Clarke7792ce2013-01-08 19:21:02 -06001017 if (ret != EDID_LENGTH) {
Jean-Francois Moine704d63f2014-01-25 18:14:46 +01001018 dev_err(encoder->dev->dev, "failed to read edid block %d: %d\n",
Rob Clarke7792ce2013-01-08 19:21:02 -06001019 blk, ret);
1020 return ret;
1021 }
1022
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001023 reg_clear(priv, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD);
Rob Clarke7792ce2013-01-08 19:21:02 -06001024
1025 return 0;
1026}
1027
1028static uint8_t *
1029do_get_edid(struct drm_encoder *encoder)
1030{
Russell King063b4722013-08-14 21:43:26 +02001031 struct tda998x_priv *priv = to_tda998x_priv(encoder);
Jean-Francois Moine704d63f2014-01-25 18:14:46 +01001032 int j, valid_extensions = 0;
Rob Clarke7792ce2013-01-08 19:21:02 -06001033 uint8_t *block, *new;
1034 bool print_bad_edid = drm_debug & DRM_UT_KMS;
1035
1036 if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL)
1037 return NULL;
1038
Russell King063b4722013-08-14 21:43:26 +02001039 if (priv->rev == TDA19988)
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001040 reg_clear(priv, REG_TX4, TX4_PD_RAM);
Russell King063b4722013-08-14 21:43:26 +02001041
Rob Clarke7792ce2013-01-08 19:21:02 -06001042 /* base block fetch */
1043 if (read_edid_block(encoder, block, 0))
1044 goto fail;
1045
1046 if (!drm_edid_block_valid(block, 0, print_bad_edid))
1047 goto fail;
1048
1049 /* if there's no extensions, we're done */
1050 if (block[0x7e] == 0)
Russell King063b4722013-08-14 21:43:26 +02001051 goto done;
Rob Clarke7792ce2013-01-08 19:21:02 -06001052
1053 new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL);
1054 if (!new)
1055 goto fail;
1056 block = new;
1057
1058 for (j = 1; j <= block[0x7e]; j++) {
1059 uint8_t *ext_block = block + (valid_extensions + 1) * EDID_LENGTH;
1060 if (read_edid_block(encoder, ext_block, j))
1061 goto fail;
1062
1063 if (!drm_edid_block_valid(ext_block, j, print_bad_edid))
1064 goto fail;
1065
1066 valid_extensions++;
1067 }
1068
1069 if (valid_extensions != block[0x7e]) {
1070 block[EDID_LENGTH-1] += block[0x7e] - valid_extensions;
1071 block[0x7e] = valid_extensions;
1072 new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
1073 if (!new)
1074 goto fail;
1075 block = new;
1076 }
1077
Russell King063b4722013-08-14 21:43:26 +02001078done:
1079 if (priv->rev == TDA19988)
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001080 reg_set(priv, REG_TX4, TX4_PD_RAM);
Russell King063b4722013-08-14 21:43:26 +02001081
Rob Clarke7792ce2013-01-08 19:21:02 -06001082 return block;
1083
1084fail:
Russell King063b4722013-08-14 21:43:26 +02001085 if (priv->rev == TDA19988)
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001086 reg_set(priv, REG_TX4, TX4_PD_RAM);
Rob Clarke7792ce2013-01-08 19:21:02 -06001087 dev_warn(encoder->dev->dev, "failed to read EDID\n");
1088 kfree(block);
1089 return NULL;
1090}
1091
1092static int
1093tda998x_encoder_get_modes(struct drm_encoder *encoder,
1094 struct drm_connector *connector)
1095{
Russell Kingc4c11dd2013-08-14 21:43:30 +02001096 struct tda998x_priv *priv = to_tda998x_priv(encoder);
Rob Clarke7792ce2013-01-08 19:21:02 -06001097 struct edid *edid = (struct edid *)do_get_edid(encoder);
1098 int n = 0;
1099
1100 if (edid) {
1101 drm_mode_connector_update_edid_property(connector, edid);
1102 n = drm_add_edid_modes(connector, edid);
Russell Kingc4c11dd2013-08-14 21:43:30 +02001103 priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid);
Rob Clarke7792ce2013-01-08 19:21:02 -06001104 kfree(edid);
1105 }
1106
1107 return n;
1108}
1109
1110static int
1111tda998x_encoder_create_resources(struct drm_encoder *encoder,
1112 struct drm_connector *connector)
1113{
1114 DBG("");
1115 return 0;
1116}
1117
1118static int
1119tda998x_encoder_set_property(struct drm_encoder *encoder,
1120 struct drm_connector *connector,
1121 struct drm_property *property,
1122 uint64_t val)
1123{
1124 DBG("");
1125 return 0;
1126}
1127
1128static void
1129tda998x_encoder_destroy(struct drm_encoder *encoder)
1130{
1131 struct tda998x_priv *priv = to_tda998x_priv(encoder);
1132 drm_i2c_encoder_destroy(encoder);
Jean-Francois Moinefc275a72014-01-25 18:14:42 +01001133 if (priv->cec)
1134 i2c_unregister_device(priv->cec);
Rob Clarke7792ce2013-01-08 19:21:02 -06001135 kfree(priv);
1136}
1137
1138static struct drm_encoder_slave_funcs tda998x_encoder_funcs = {
1139 .set_config = tda998x_encoder_set_config,
1140 .destroy = tda998x_encoder_destroy,
1141 .dpms = tda998x_encoder_dpms,
1142 .save = tda998x_encoder_save,
1143 .restore = tda998x_encoder_restore,
1144 .mode_fixup = tda998x_encoder_mode_fixup,
1145 .mode_valid = tda998x_encoder_mode_valid,
1146 .mode_set = tda998x_encoder_mode_set,
1147 .detect = tda998x_encoder_detect,
1148 .get_modes = tda998x_encoder_get_modes,
1149 .create_resources = tda998x_encoder_create_resources,
1150 .set_property = tda998x_encoder_set_property,
1151};
1152
1153/* I2C driver functions */
1154
1155static int
1156tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id)
1157{
1158 return 0;
1159}
1160
1161static int
1162tda998x_remove(struct i2c_client *client)
1163{
1164 return 0;
1165}
1166
1167static int
1168tda998x_encoder_init(struct i2c_client *client,
1169 struct drm_device *dev,
1170 struct drm_encoder_slave *encoder_slave)
1171{
Rob Clarke7792ce2013-01-08 19:21:02 -06001172 struct tda998x_priv *priv;
Russell Kingfb7544d2014-02-02 16:18:24 +00001173 int rev_lo, rev_hi, ret;
Rob Clarke7792ce2013-01-08 19:21:02 -06001174
1175 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1176 if (!priv)
1177 return -ENOMEM;
1178
Russell King5e74c222013-08-14 21:43:29 +02001179 priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3);
1180 priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1);
1181 priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5);
1182
Jean-Francois Moine2eb4c7b2014-01-25 18:14:45 +01001183 priv->current_page = 0xff;
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001184 priv->hdmi = client;
Rob Clarke7792ce2013-01-08 19:21:02 -06001185 priv->cec = i2c_new_dummy(client->adapter, 0x34);
Dave Jones71c68c42014-02-12 22:47:51 -05001186 if (!priv->cec) {
1187 kfree(priv);
Jean-Francois Moine6ae668c2014-01-25 18:14:43 +01001188 return -ENODEV;
Dave Jones71c68c42014-02-12 22:47:51 -05001189 }
Rob Clarke7792ce2013-01-08 19:21:02 -06001190 priv->dpms = DRM_MODE_DPMS_OFF;
1191
1192 encoder_slave->slave_priv = priv;
1193 encoder_slave->slave_funcs = &tda998x_encoder_funcs;
1194
1195 /* wake up the device: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001196 cec_write(priv, REG_CEC_ENAMODS,
Rob Clarke7792ce2013-01-08 19:21:02 -06001197 CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI);
1198
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001199 tda998x_reset(priv);
Rob Clarke7792ce2013-01-08 19:21:02 -06001200
1201 /* read version: */
Russell Kingfb7544d2014-02-02 16:18:24 +00001202 rev_lo = reg_read(priv, REG_VERSION_LSB);
1203 rev_hi = reg_read(priv, REG_VERSION_MSB);
1204 if (rev_lo < 0 || rev_hi < 0) {
1205 ret = rev_lo < 0 ? rev_lo : rev_hi;
Jean-Francois Moine7d2eadc2014-01-25 18:14:45 +01001206 goto fail;
Russell Kingfb7544d2014-02-02 16:18:24 +00001207 }
1208
1209 priv->rev = rev_lo | rev_hi << 8;
Rob Clarke7792ce2013-01-08 19:21:02 -06001210
1211 /* mask off feature bits: */
1212 priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */
1213
1214 switch (priv->rev) {
Jean-Francois Moineb728fab2014-01-25 18:14:46 +01001215 case TDA9989N2:
1216 dev_info(&client->dev, "found TDA9989 n2");
1217 break;
1218 case TDA19989:
1219 dev_info(&client->dev, "found TDA19989");
1220 break;
1221 case TDA19989N2:
1222 dev_info(&client->dev, "found TDA19989 n2");
1223 break;
1224 case TDA19988:
1225 dev_info(&client->dev, "found TDA19988");
1226 break;
Rob Clarke7792ce2013-01-08 19:21:02 -06001227 default:
Jean-Francois Moineb728fab2014-01-25 18:14:46 +01001228 dev_err(&client->dev, "found unsupported device: %04x\n",
1229 priv->rev);
Rob Clarke7792ce2013-01-08 19:21:02 -06001230 goto fail;
1231 }
1232
1233 /* after reset, enable DDC: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001234 reg_write(priv, REG_DDC_DISABLE, 0x00);
Rob Clarke7792ce2013-01-08 19:21:02 -06001235
1236 /* set clock on DDC channel: */
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001237 reg_write(priv, REG_TX3, 39);
Rob Clarke7792ce2013-01-08 19:21:02 -06001238
1239 /* if necessary, disable multi-master: */
1240 if (priv->rev == TDA19989)
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001241 reg_set(priv, REG_I2C_MASTER, I2C_MASTER_DIS_MM);
Rob Clarke7792ce2013-01-08 19:21:02 -06001242
Jean-Francois Moine2f7f7302014-01-25 18:14:47 +01001243 cec_write(priv, REG_CEC_FRO_IM_CLK_CTRL,
Rob Clarke7792ce2013-01-08 19:21:02 -06001244 CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL);
1245
1246 return 0;
1247
1248fail:
1249 /* if encoder_init fails, the encoder slave is never registered,
1250 * so cleanup here:
1251 */
1252 if (priv->cec)
1253 i2c_unregister_device(priv->cec);
1254 kfree(priv);
1255 encoder_slave->slave_priv = NULL;
1256 encoder_slave->slave_funcs = NULL;
1257 return -ENXIO;
1258}
1259
1260static struct i2c_device_id tda998x_ids[] = {
1261 { "tda998x", 0 },
1262 { }
1263};
1264MODULE_DEVICE_TABLE(i2c, tda998x_ids);
1265
1266static struct drm_i2c_encoder_driver tda998x_driver = {
1267 .i2c_driver = {
1268 .probe = tda998x_probe,
1269 .remove = tda998x_remove,
1270 .driver = {
1271 .name = "tda998x",
1272 },
1273 .id_table = tda998x_ids,
1274 },
1275 .encoder_init = tda998x_encoder_init,
1276};
1277
1278/* Module initialization */
1279
1280static int __init
1281tda998x_init(void)
1282{
1283 DBG("");
1284 return drm_i2c_encoder_register(THIS_MODULE, &tda998x_driver);
1285}
1286
1287static void __exit
1288tda998x_exit(void)
1289{
1290 DBG("");
1291 drm_i2c_encoder_unregister(&tda998x_driver);
1292}
1293
1294MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
1295MODULE_DESCRIPTION("NXP Semiconductors TDA998X HDMI Encoder");
1296MODULE_LICENSE("GPL");
1297
1298module_init(tda998x_init);
1299module_exit(tda998x_exit);