diff options
author | Mats Randgaard <matrandg@cisco.com> | 2015-07-09 04:45:47 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2015-07-17 08:59:28 -0400 |
commit | d32d98642de66048f9534a05f3641558e811bbc9 (patch) | |
tree | ce1b6a91bd269350bd6e5cba0656b2fd6fc1dc24 | |
parent | bde2b96d6dfb1c14e5d27a4e7e7d492e9be102cd (diff) |
[media] Driver for Toshiba TC358743 HDMI to CSI-2 bridge
The driver is tested on our hardware and all the implemented features
works as expected.
Missing features:
- CEC support
- HDCP repeater support
- IR support
Signed-off-by: Mats Randgaard <matrandg@cisco.com>
[hans.verkuil@cisco.com: updated copyright year to 2015]
[hans.verkuil@cisco.com: update confusing confctl_mutex comment]
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
-rw-r--r-- | MAINTAINERS | 7 | ||||
-rw-r--r-- | drivers/media/i2c/Kconfig | 9 | ||||
-rw-r--r-- | drivers/media/i2c/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/i2c/tc358743.c | 1778 | ||||
-rw-r--r-- | drivers/media/i2c/tc358743_regs.h | 681 | ||||
-rw-r--r-- | include/media/tc358743.h | 131 | ||||
-rw-r--r-- | include/uapi/linux/v4l2-controls.h | 4 |
7 files changed, 2611 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index fd6078443083..2bb989be111d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -10319,6 +10319,13 @@ F: drivers/char/toshiba.c | |||
10319 | F: include/linux/toshiba.h | 10319 | F: include/linux/toshiba.h |
10320 | F: include/uapi/linux/toshiba.h | 10320 | F: include/uapi/linux/toshiba.h |
10321 | 10321 | ||
10322 | TOSHIBA TC358743 DRIVER | ||
10323 | M: Mats Randgaard <matrandg@cisco.com> | ||
10324 | L: linux-media@vger.kernel.org | ||
10325 | S: Maintained | ||
10326 | F: drivers/media/i2c/tc358743* | ||
10327 | F: include/media/tc358743.h | ||
10328 | |||
10322 | TMIO MMC DRIVER | 10329 | TMIO MMC DRIVER |
10323 | M: Ian Molton <ian@mnementh.co.uk> | 10330 | M: Ian Molton <ian@mnementh.co.uk> |
10324 | L: linux-mmc@vger.kernel.org | 10331 | L: linux-mmc@vger.kernel.org |
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 8d1268648fe0..0e0490d60e7e 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig | |||
@@ -287,6 +287,15 @@ config VIDEO_SAA711X | |||
287 | To compile this driver as a module, choose M here: the | 287 | To compile this driver as a module, choose M here: the |
288 | module will be called saa7115. | 288 | module will be called saa7115. |
289 | 289 | ||
290 | config VIDEO_TC358743 | ||
291 | tristate "Toshiba TC358743 decoder" | ||
292 | depends on VIDEO_V4L2 && I2C | ||
293 | ---help--- | ||
294 | Support for the Toshiba TC358743 HDMI to MIPI CSI-2 bridge. | ||
295 | |||
296 | To compile this driver as a module, choose M here: the | ||
297 | module will be called tc358743. | ||
298 | |||
290 | config VIDEO_TVP514X | 299 | config VIDEO_TVP514X |
291 | tristate "Texas Instruments TVP514x video decoder" | 300 | tristate "Texas Instruments TVP514x video decoder" |
292 | depends on VIDEO_V4L2 && I2C | 301 | depends on VIDEO_V4L2 && I2C |
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index f165faea5b3f..07db257abfc1 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile | |||
@@ -78,3 +78,4 @@ obj-$(CONFIG_VIDEO_AK881X) += ak881x.o | |||
78 | obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o | 78 | obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o |
79 | obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o | 79 | obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o |
80 | obj-$(CONFIG_VIDEO_OV2659) += ov2659.o | 80 | obj-$(CONFIG_VIDEO_OV2659) += ov2659.o |
81 | obj-$(CONFIG_VIDEO_TC358743) += tc358743.o | ||
diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c new file mode 100644 index 000000000000..4e8811c3e771 --- /dev/null +++ b/drivers/media/i2c/tc358743.c | |||
@@ -0,0 +1,1778 @@ | |||
1 | /* | ||
2 | * tc358743 - Toshiba HDMI to CSI-2 bridge | ||
3 | * | ||
4 | * Copyright 2015 Cisco Systems, Inc. and/or its affiliates. All rights | ||
5 | * reserved. | ||
6 | * | ||
7 | * This program is free software; you may redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
12 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
13 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
15 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
16 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
17 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
18 | * SOFTWARE. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * References (c = chapter, p = page): | ||
24 | * REF_01 - Toshiba, TC358743XBG (H2C), Functional Specification, Rev 0.60 | ||
25 | * REF_02 - Toshiba, TC358743XBG_HDMI-CSI_Tv11p_nm.xls | ||
26 | */ | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/videodev2.h> | ||
34 | #include <linux/workqueue.h> | ||
35 | #include <linux/v4l2-dv-timings.h> | ||
36 | #include <linux/hdmi.h> | ||
37 | #include <media/v4l2-dv-timings.h> | ||
38 | #include <media/v4l2-device.h> | ||
39 | #include <media/v4l2-ctrls.h> | ||
40 | #include <media/tc358743.h> | ||
41 | |||
42 | #include "tc358743_regs.h" | ||
43 | |||
44 | static int debug; | ||
45 | module_param(debug, int, 0644); | ||
46 | MODULE_PARM_DESC(debug, "debug level (0-3)"); | ||
47 | |||
48 | MODULE_DESCRIPTION("Toshiba TC358743 HDMI to CSI-2 bridge driver"); | ||
49 | MODULE_AUTHOR("Ramakrishnan Muthukrishnan <ram@rkrishnan.org>"); | ||
50 | MODULE_AUTHOR("Mikhail Khelik <mkhelik@cisco.com>"); | ||
51 | MODULE_AUTHOR("Mats Randgaard <matrandg@cisco.com>"); | ||
52 | MODULE_LICENSE("GPL"); | ||
53 | |||
54 | #define EDID_NUM_BLOCKS_MAX 8 | ||
55 | #define EDID_BLOCK_SIZE 128 | ||
56 | |||
57 | static const struct v4l2_dv_timings_cap tc358743_timings_cap = { | ||
58 | .type = V4L2_DV_BT_656_1120, | ||
59 | /* keep this initialization for compatibility with GCC < 4.4.6 */ | ||
60 | .reserved = { 0 }, | ||
61 | /* Pixel clock from REF_01 p. 20. Min/max height/width are unknown */ | ||
62 | V4L2_INIT_BT_TIMINGS(1, 10000, 1, 10000, 0, 165000000, | ||
63 | V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT | | ||
64 | V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT, | ||
65 | V4L2_DV_BT_CAP_PROGRESSIVE | | ||
66 | V4L2_DV_BT_CAP_REDUCED_BLANKING | | ||
67 | V4L2_DV_BT_CAP_CUSTOM) | ||
68 | }; | ||
69 | |||
70 | struct tc358743_state { | ||
71 | struct tc358743_platform_data pdata; | ||
72 | struct v4l2_subdev sd; | ||
73 | struct media_pad pad; | ||
74 | struct v4l2_ctrl_handler hdl; | ||
75 | struct i2c_client *i2c_client; | ||
76 | /* CONFCTL is modified in ops and tc358743_hdmi_sys_int_handler */ | ||
77 | struct mutex confctl_mutex; | ||
78 | |||
79 | /* controls */ | ||
80 | struct v4l2_ctrl *detect_tx_5v_ctrl; | ||
81 | struct v4l2_ctrl *audio_sampling_rate_ctrl; | ||
82 | struct v4l2_ctrl *audio_present_ctrl; | ||
83 | |||
84 | /* work queues */ | ||
85 | struct workqueue_struct *work_queues; | ||
86 | struct delayed_work delayed_work_enable_hotplug; | ||
87 | |||
88 | /* edid */ | ||
89 | u8 edid_blocks_written; | ||
90 | |||
91 | struct v4l2_dv_timings timings; | ||
92 | u32 mbus_fmt_code; | ||
93 | }; | ||
94 | |||
95 | static void tc358743_enable_interrupts(struct v4l2_subdev *sd, | ||
96 | bool cable_connected); | ||
97 | static int tc358743_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd); | ||
98 | |||
99 | static inline struct tc358743_state *to_state(struct v4l2_subdev *sd) | ||
100 | { | ||
101 | return container_of(sd, struct tc358743_state, sd); | ||
102 | } | ||
103 | |||
104 | /* --------------- I2C --------------- */ | ||
105 | |||
106 | static void i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) | ||
107 | { | ||
108 | struct tc358743_state *state = to_state(sd); | ||
109 | struct i2c_client *client = state->i2c_client; | ||
110 | int err; | ||
111 | u8 buf[2] = { reg >> 8, reg & 0xff }; | ||
112 | struct i2c_msg msgs[] = { | ||
113 | { | ||
114 | .addr = client->addr, | ||
115 | .flags = 0, | ||
116 | .len = 2, | ||
117 | .buf = buf, | ||
118 | }, | ||
119 | { | ||
120 | .addr = client->addr, | ||
121 | .flags = I2C_M_RD, | ||
122 | .len = n, | ||
123 | .buf = values, | ||
124 | }, | ||
125 | }; | ||
126 | |||
127 | err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
128 | if (err != ARRAY_SIZE(msgs)) { | ||
129 | v4l2_err(sd, "%s: reading register 0x%x from 0x%x failed\n", | ||
130 | __func__, reg, client->addr); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n) | ||
135 | { | ||
136 | struct tc358743_state *state = to_state(sd); | ||
137 | struct i2c_client *client = state->i2c_client; | ||
138 | int err, i; | ||
139 | struct i2c_msg msg; | ||
140 | u8 data[2 + n]; | ||
141 | |||
142 | msg.addr = client->addr; | ||
143 | msg.buf = data; | ||
144 | msg.len = 2 + n; | ||
145 | msg.flags = 0; | ||
146 | |||
147 | data[0] = reg >> 8; | ||
148 | data[1] = reg & 0xff; | ||
149 | |||
150 | for (i = 0; i < n; i++) | ||
151 | data[2 + i] = values[i]; | ||
152 | |||
153 | err = i2c_transfer(client->adapter, &msg, 1); | ||
154 | if (err != 1) { | ||
155 | v4l2_err(sd, "%s: writing register 0x%x from 0x%x failed\n", | ||
156 | __func__, reg, client->addr); | ||
157 | return; | ||
158 | } | ||
159 | |||
160 | if (debug < 3) | ||
161 | return; | ||
162 | |||
163 | switch (n) { | ||
164 | case 1: | ||
165 | v4l2_info(sd, "I2C write 0x%04x = 0x%02x", | ||
166 | reg, data[2]); | ||
167 | break; | ||
168 | case 2: | ||
169 | v4l2_info(sd, "I2C write 0x%04x = 0x%02x%02x", | ||
170 | reg, data[3], data[2]); | ||
171 | break; | ||
172 | case 4: | ||
173 | v4l2_info(sd, "I2C write 0x%04x = 0x%02x%02x%02x%02x", | ||
174 | reg, data[5], data[4], data[3], data[2]); | ||
175 | break; | ||
176 | default: | ||
177 | v4l2_info(sd, "I2C write %d bytes from address 0x%04x\n", | ||
178 | n, reg); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | static u8 i2c_rd8(struct v4l2_subdev *sd, u16 reg) | ||
183 | { | ||
184 | u8 val; | ||
185 | |||
186 | i2c_rd(sd, reg, &val, 1); | ||
187 | |||
188 | return val; | ||
189 | } | ||
190 | |||
191 | static void i2c_wr8(struct v4l2_subdev *sd, u16 reg, u8 val) | ||
192 | { | ||
193 | i2c_wr(sd, reg, &val, 1); | ||
194 | } | ||
195 | |||
196 | static void i2c_wr8_and_or(struct v4l2_subdev *sd, u16 reg, | ||
197 | u8 mask, u8 val) | ||
198 | { | ||
199 | i2c_wr8(sd, reg, (i2c_rd8(sd, reg) & mask) | val); | ||
200 | } | ||
201 | |||
202 | static u16 i2c_rd16(struct v4l2_subdev *sd, u16 reg) | ||
203 | { | ||
204 | u16 val; | ||
205 | |||
206 | i2c_rd(sd, reg, (u8 *)&val, 2); | ||
207 | |||
208 | return val; | ||
209 | } | ||
210 | |||
211 | static void i2c_wr16(struct v4l2_subdev *sd, u16 reg, u16 val) | ||
212 | { | ||
213 | i2c_wr(sd, reg, (u8 *)&val, 2); | ||
214 | } | ||
215 | |||
216 | static void i2c_wr16_and_or(struct v4l2_subdev *sd, u16 reg, u16 mask, u16 val) | ||
217 | { | ||
218 | i2c_wr16(sd, reg, (i2c_rd16(sd, reg) & mask) | val); | ||
219 | } | ||
220 | |||
221 | static u32 i2c_rd32(struct v4l2_subdev *sd, u16 reg) | ||
222 | { | ||
223 | u32 val; | ||
224 | |||
225 | i2c_rd(sd, reg, (u8 *)&val, 4); | ||
226 | |||
227 | return val; | ||
228 | } | ||
229 | |||
230 | static void i2c_wr32(struct v4l2_subdev *sd, u16 reg, u32 val) | ||
231 | { | ||
232 | i2c_wr(sd, reg, (u8 *)&val, 4); | ||
233 | } | ||
234 | |||
235 | /* --------------- STATUS --------------- */ | ||
236 | |||
237 | static inline bool is_hdmi(struct v4l2_subdev *sd) | ||
238 | { | ||
239 | return i2c_rd8(sd, SYS_STATUS) & MASK_S_HDMI; | ||
240 | } | ||
241 | |||
242 | static inline bool tx_5v_power_present(struct v4l2_subdev *sd) | ||
243 | { | ||
244 | return i2c_rd8(sd, SYS_STATUS) & MASK_S_DDC5V; | ||
245 | } | ||
246 | |||
247 | static inline bool no_signal(struct v4l2_subdev *sd) | ||
248 | { | ||
249 | return !(i2c_rd8(sd, SYS_STATUS) & MASK_S_TMDS); | ||
250 | } | ||
251 | |||
252 | static inline bool no_sync(struct v4l2_subdev *sd) | ||
253 | { | ||
254 | return !(i2c_rd8(sd, SYS_STATUS) & MASK_S_SYNC); | ||
255 | } | ||
256 | |||
257 | static inline bool audio_present(struct v4l2_subdev *sd) | ||
258 | { | ||
259 | return i2c_rd8(sd, AU_STATUS0) & MASK_S_A_SAMPLE; | ||
260 | } | ||
261 | |||
262 | static int get_audio_sampling_rate(struct v4l2_subdev *sd) | ||
263 | { | ||
264 | static const int code_to_rate[] = { | ||
265 | 44100, 0, 48000, 32000, 22050, 384000, 24000, 352800, | ||
266 | 88200, 768000, 96000, 705600, 176400, 0, 192000, 0 | ||
267 | }; | ||
268 | |||
269 | /* Register FS_SET is not cleared when the cable is disconnected */ | ||
270 | if (no_signal(sd)) | ||
271 | return 0; | ||
272 | |||
273 | return code_to_rate[i2c_rd8(sd, FS_SET) & MASK_FS]; | ||
274 | } | ||
275 | |||
276 | static unsigned tc358743_num_csi_lanes_in_use(struct v4l2_subdev *sd) | ||
277 | { | ||
278 | return ((i2c_rd32(sd, CSI_CONTROL) & MASK_NOL) >> 1) + 1; | ||
279 | } | ||
280 | |||
281 | /* --------------- TIMINGS --------------- */ | ||
282 | |||
283 | static inline unsigned fps(const struct v4l2_bt_timings *t) | ||
284 | { | ||
285 | if (!V4L2_DV_BT_FRAME_HEIGHT(t) || !V4L2_DV_BT_FRAME_WIDTH(t)) | ||
286 | return 0; | ||
287 | |||
288 | return DIV_ROUND_CLOSEST((unsigned)t->pixelclock, | ||
289 | V4L2_DV_BT_FRAME_HEIGHT(t) * V4L2_DV_BT_FRAME_WIDTH(t)); | ||
290 | } | ||
291 | |||
292 | static int tc358743_get_detected_timings(struct v4l2_subdev *sd, | ||
293 | struct v4l2_dv_timings *timings) | ||
294 | { | ||
295 | struct v4l2_bt_timings *bt = &timings->bt; | ||
296 | unsigned width, height, frame_width, frame_height, frame_interval, fps; | ||
297 | |||
298 | memset(timings, 0, sizeof(struct v4l2_dv_timings)); | ||
299 | |||
300 | if (no_signal(sd)) { | ||
301 | v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__); | ||
302 | return -ENOLINK; | ||
303 | } | ||
304 | if (no_sync(sd)) { | ||
305 | v4l2_dbg(1, debug, sd, "%s: no sync on signal\n", __func__); | ||
306 | return -ENOLCK; | ||
307 | } | ||
308 | |||
309 | timings->type = V4L2_DV_BT_656_1120; | ||
310 | bt->interlaced = i2c_rd8(sd, VI_STATUS1) & MASK_S_V_INTERLACE ? | ||
311 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; | ||
312 | |||
313 | width = ((i2c_rd8(sd, DE_WIDTH_H_HI) & 0x1f) << 8) + | ||
314 | i2c_rd8(sd, DE_WIDTH_H_LO); | ||
315 | height = ((i2c_rd8(sd, DE_WIDTH_V_HI) & 0x1f) << 8) + | ||
316 | i2c_rd8(sd, DE_WIDTH_V_LO); | ||
317 | frame_width = ((i2c_rd8(sd, H_SIZE_HI) & 0x1f) << 8) + | ||
318 | i2c_rd8(sd, H_SIZE_LO); | ||
319 | frame_height = (((i2c_rd8(sd, V_SIZE_HI) & 0x3f) << 8) + | ||
320 | i2c_rd8(sd, V_SIZE_LO)) / 2; | ||
321 | /* frame interval in milliseconds * 10 | ||
322 | * Require SYS_FREQ0 and SYS_FREQ1 are precisely set */ | ||
323 | frame_interval = ((i2c_rd8(sd, FV_CNT_HI) & 0x3) << 8) + | ||
324 | i2c_rd8(sd, FV_CNT_LO); | ||
325 | fps = (frame_interval > 0) ? | ||
326 | DIV_ROUND_CLOSEST(10000, frame_interval) : 0; | ||
327 | |||
328 | bt->width = width; | ||
329 | bt->height = height; | ||
330 | bt->vsync = frame_height - height; | ||
331 | bt->hsync = frame_width - width; | ||
332 | bt->pixelclock = frame_width * frame_height * fps; | ||
333 | if (bt->interlaced == V4L2_DV_INTERLACED) { | ||
334 | bt->height *= 2; | ||
335 | bt->il_vsync = bt->vsync + 1; | ||
336 | bt->pixelclock /= 2; | ||
337 | } | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | /* --------------- HOTPLUG / HDCP / EDID --------------- */ | ||
343 | |||
344 | static void tc358743_delayed_work_enable_hotplug(struct work_struct *work) | ||
345 | { | ||
346 | struct delayed_work *dwork = to_delayed_work(work); | ||
347 | struct tc358743_state *state = container_of(dwork, | ||
348 | struct tc358743_state, delayed_work_enable_hotplug); | ||
349 | struct v4l2_subdev *sd = &state->sd; | ||
350 | |||
351 | v4l2_dbg(2, debug, sd, "%s:\n", __func__); | ||
352 | |||
353 | i2c_wr8_and_or(sd, HPD_CTL, ~MASK_HPD_OUT0, MASK_HPD_OUT0); | ||
354 | } | ||
355 | |||
356 | static void tc358743_set_hdmi_hdcp(struct v4l2_subdev *sd, bool enable) | ||
357 | { | ||
358 | v4l2_dbg(2, debug, sd, "%s: %s\n", __func__, enable ? | ||
359 | "enable" : "disable"); | ||
360 | |||
361 | i2c_wr8_and_or(sd, HDCP_REG1, | ||
362 | ~(MASK_AUTH_UNAUTH_SEL | MASK_AUTH_UNAUTH), | ||
363 | MASK_AUTH_UNAUTH_SEL_16_FRAMES | MASK_AUTH_UNAUTH_AUTO); | ||
364 | |||
365 | i2c_wr8_and_or(sd, HDCP_REG2, ~MASK_AUTO_P3_RESET, | ||
366 | SET_AUTO_P3_RESET_FRAMES(0x0f)); | ||
367 | |||
368 | /* HDCP is disabled by configuring the receiver as HDCP repeater. The | ||
369 | * repeater mode require software support to work, so HDCP | ||
370 | * authentication will fail. | ||
371 | */ | ||
372 | i2c_wr8_and_or(sd, HDCP_REG3, ~KEY_RD_CMD, enable ? KEY_RD_CMD : 0); | ||
373 | i2c_wr8_and_or(sd, HDCP_MODE, ~(MASK_AUTO_CLR | MASK_MODE_RST_TN), | ||
374 | enable ? (MASK_AUTO_CLR | MASK_MODE_RST_TN) : 0); | ||
375 | |||
376 | /* Apple MacBook Pro gen.8 has a bug that makes it freeze every fifth | ||
377 | * second when HDCP is disabled, but the MAX_EXCED bit is handled | ||
378 | * correctly and HDCP is disabled on the HDMI output. | ||
379 | */ | ||
380 | i2c_wr8_and_or(sd, BSTATUS1, ~MASK_MAX_EXCED, | ||
381 | enable ? 0 : MASK_MAX_EXCED); | ||
382 | i2c_wr8_and_or(sd, BCAPS, ~(MASK_REPEATER | MASK_READY), | ||
383 | enable ? 0 : MASK_REPEATER | MASK_READY); | ||
384 | } | ||
385 | |||
386 | static void tc358743_disable_edid(struct v4l2_subdev *sd) | ||
387 | { | ||
388 | struct tc358743_state *state = to_state(sd); | ||
389 | |||
390 | v4l2_dbg(2, debug, sd, "%s:\n", __func__); | ||
391 | |||
392 | cancel_delayed_work_sync(&state->delayed_work_enable_hotplug); | ||
393 | |||
394 | /* DDC access to EDID is also disabled when hotplug is disabled. See | ||
395 | * register DDC_CTL */ | ||
396 | i2c_wr8_and_or(sd, HPD_CTL, ~MASK_HPD_OUT0, 0x0); | ||
397 | } | ||
398 | |||
399 | static void tc358743_enable_edid(struct v4l2_subdev *sd) | ||
400 | { | ||
401 | struct tc358743_state *state = to_state(sd); | ||
402 | |||
403 | if (state->edid_blocks_written == 0) { | ||
404 | v4l2_dbg(2, debug, sd, "%s: no EDID -> no hotplug\n", __func__); | ||
405 | return; | ||
406 | } | ||
407 | |||
408 | v4l2_dbg(2, debug, sd, "%s:\n", __func__); | ||
409 | |||
410 | /* Enable hotplug after 100 ms. DDC access to EDID is also enabled when | ||
411 | * hotplug is enabled. See register DDC_CTL */ | ||
412 | queue_delayed_work(state->work_queues, | ||
413 | &state->delayed_work_enable_hotplug, HZ / 10); | ||
414 | |||
415 | tc358743_enable_interrupts(sd, true); | ||
416 | tc358743_s_ctrl_detect_tx_5v(sd); | ||
417 | } | ||
418 | |||
419 | static void tc358743_erase_bksv(struct v4l2_subdev *sd) | ||
420 | { | ||
421 | int i; | ||
422 | |||
423 | for (i = 0; i < 5; i++) | ||
424 | i2c_wr8(sd, BKSV + i, 0); | ||
425 | } | ||
426 | |||
427 | /* --------------- AVI infoframe --------------- */ | ||
428 | |||
429 | static void print_avi_infoframe(struct v4l2_subdev *sd) | ||
430 | { | ||
431 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
432 | struct device *dev = &client->dev; | ||
433 | union hdmi_infoframe frame; | ||
434 | u8 buffer[HDMI_INFOFRAME_SIZE(AVI)]; | ||
435 | |||
436 | if (!is_hdmi(sd)) { | ||
437 | v4l2_info(sd, "DVI-D signal - AVI infoframe not supported\n"); | ||
438 | return; | ||
439 | } | ||
440 | |||
441 | i2c_rd(sd, PK_AVI_0HEAD, buffer, HDMI_INFOFRAME_SIZE(AVI)); | ||
442 | |||
443 | if (hdmi_infoframe_unpack(&frame, buffer) < 0) { | ||
444 | v4l2_err(sd, "%s: unpack of AVI infoframe failed\n", __func__); | ||
445 | return; | ||
446 | } | ||
447 | |||
448 | hdmi_infoframe_log(KERN_INFO, dev, &frame); | ||
449 | } | ||
450 | |||
451 | /* --------------- CTRLS --------------- */ | ||
452 | |||
453 | static int tc358743_s_ctrl_detect_tx_5v(struct v4l2_subdev *sd) | ||
454 | { | ||
455 | struct tc358743_state *state = to_state(sd); | ||
456 | |||
457 | return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, | ||
458 | tx_5v_power_present(sd)); | ||
459 | } | ||
460 | |||
461 | static int tc358743_s_ctrl_audio_sampling_rate(struct v4l2_subdev *sd) | ||
462 | { | ||
463 | struct tc358743_state *state = to_state(sd); | ||
464 | |||
465 | return v4l2_ctrl_s_ctrl(state->audio_sampling_rate_ctrl, | ||
466 | get_audio_sampling_rate(sd)); | ||
467 | } | ||
468 | |||
469 | static int tc358743_s_ctrl_audio_present(struct v4l2_subdev *sd) | ||
470 | { | ||
471 | struct tc358743_state *state = to_state(sd); | ||
472 | |||
473 | return v4l2_ctrl_s_ctrl(state->audio_present_ctrl, | ||
474 | audio_present(sd)); | ||
475 | } | ||
476 | |||
477 | static int tc358743_update_controls(struct v4l2_subdev *sd) | ||
478 | { | ||
479 | int ret = 0; | ||
480 | |||
481 | ret |= tc358743_s_ctrl_detect_tx_5v(sd); | ||
482 | ret |= tc358743_s_ctrl_audio_sampling_rate(sd); | ||
483 | ret |= tc358743_s_ctrl_audio_present(sd); | ||
484 | |||
485 | return ret; | ||
486 | } | ||
487 | |||
488 | /* --------------- INIT --------------- */ | ||
489 | |||
490 | static void tc358743_reset_phy(struct v4l2_subdev *sd) | ||
491 | { | ||
492 | v4l2_dbg(1, debug, sd, "%s:\n", __func__); | ||
493 | |||
494 | i2c_wr8_and_or(sd, PHY_RST, ~MASK_RESET_CTRL, 0); | ||
495 | i2c_wr8_and_or(sd, PHY_RST, ~MASK_RESET_CTRL, MASK_RESET_CTRL); | ||
496 | } | ||
497 | |||
498 | static void tc358743_reset(struct v4l2_subdev *sd, uint16_t mask) | ||
499 | { | ||
500 | u16 sysctl = i2c_rd16(sd, SYSCTL); | ||
501 | |||
502 | i2c_wr16(sd, SYSCTL, sysctl | mask); | ||
503 | i2c_wr16(sd, SYSCTL, sysctl & ~mask); | ||
504 | } | ||
505 | |||
506 | static inline void tc358743_sleep_mode(struct v4l2_subdev *sd, bool enable) | ||
507 | { | ||
508 | i2c_wr16_and_or(sd, SYSCTL, ~MASK_SLEEP, | ||
509 | enable ? MASK_SLEEP : 0); | ||
510 | } | ||
511 | |||
512 | static inline void enable_stream(struct v4l2_subdev *sd, bool enable) | ||
513 | { | ||
514 | struct tc358743_state *state = to_state(sd); | ||
515 | |||
516 | v4l2_dbg(3, debug, sd, "%s: %sable\n", | ||
517 | __func__, enable ? "en" : "dis"); | ||
518 | |||
519 | if (enable) { | ||
520 | /* It is critical for CSI receiver to see lane transition | ||
521 | * LP11->HS. Set to non-continuous mode to enable clock lane | ||
522 | * LP11 state. */ | ||
523 | i2c_wr32(sd, TXOPTIONCNTRL, 0); | ||
524 | /* Set to continuous mode to trigger LP11->HS transition */ | ||
525 | i2c_wr32(sd, TXOPTIONCNTRL, MASK_CONTCLKMODE); | ||
526 | /* Unmute video */ | ||
527 | i2c_wr8(sd, VI_MUTE, MASK_AUTO_MUTE); | ||
528 | } else { | ||
529 | /* Mute video so that all data lanes go to LSP11 state. | ||
530 | * No data is output to CSI Tx block. */ | ||
531 | i2c_wr8(sd, VI_MUTE, MASK_AUTO_MUTE | MASK_VI_MUTE); | ||
532 | } | ||
533 | |||
534 | mutex_lock(&state->confctl_mutex); | ||
535 | i2c_wr16_and_or(sd, CONFCTL, ~(MASK_VBUFEN | MASK_ABUFEN), | ||
536 | enable ? (MASK_VBUFEN | MASK_ABUFEN) : 0x0); | ||
537 | mutex_unlock(&state->confctl_mutex); | ||
538 | } | ||
539 | |||
540 | static void tc358743_set_pll(struct v4l2_subdev *sd) | ||
541 | { | ||
542 | struct tc358743_state *state = to_state(sd); | ||
543 | struct tc358743_platform_data *pdata = &state->pdata; | ||
544 | u16 pllctl0 = i2c_rd16(sd, PLLCTL0); | ||
545 | u16 pllctl1 = i2c_rd16(sd, PLLCTL1); | ||
546 | u16 pllctl0_new = SET_PLL_PRD(pdata->pll_prd) | | ||
547 | SET_PLL_FBD(pdata->pll_fbd); | ||
548 | u32 hsck = (pdata->refclk_hz / pdata->pll_prd) * pdata->pll_fbd; | ||
549 | |||
550 | v4l2_dbg(2, debug, sd, "%s:\n", __func__); | ||
551 | |||
552 | /* Only rewrite when needed (new value or disabled), since rewriting | ||
553 | * triggers another format change event. */ | ||
554 | if ((pllctl0 != pllctl0_new) || ((pllctl1 & MASK_PLL_EN) == 0)) { | ||
555 | u16 pll_frs; | ||
556 | |||
557 | if (hsck > 500000000) | ||
558 | pll_frs = 0x0; | ||
559 | else if (hsck > 250000000) | ||
560 | pll_frs = 0x1; | ||
561 | else if (hsck > 125000000) | ||
562 | pll_frs = 0x2; | ||
563 | else | ||
564 | pll_frs = 0x3; | ||
565 | |||
566 | v4l2_dbg(1, debug, sd, "%s: updating PLL clock\n", __func__); | ||
567 | tc358743_sleep_mode(sd, true); | ||
568 | i2c_wr16(sd, PLLCTL0, pllctl0_new); | ||
569 | i2c_wr16_and_or(sd, PLLCTL1, | ||
570 | ~(MASK_PLL_FRS | MASK_RESETB | MASK_PLL_EN), | ||
571 | (SET_PLL_FRS(pll_frs) | MASK_RESETB | | ||
572 | MASK_PLL_EN)); | ||
573 | udelay(10); /* REF_02, Sheet "Source HDMI" */ | ||
574 | i2c_wr16_and_or(sd, PLLCTL1, ~MASK_CKEN, MASK_CKEN); | ||
575 | tc358743_sleep_mode(sd, false); | ||
576 | } | ||
577 | } | ||
578 | |||
579 | static void tc358743_set_ref_clk(struct v4l2_subdev *sd) | ||
580 | { | ||
581 | struct tc358743_state *state = to_state(sd); | ||
582 | struct tc358743_platform_data *pdata = &state->pdata; | ||
583 | u32 sys_freq; | ||
584 | u32 lockdet_ref; | ||
585 | u16 fh_min; | ||
586 | u16 fh_max; | ||
587 | |||
588 | BUG_ON(!(pdata->refclk_hz == 26000000 || | ||
589 | pdata->refclk_hz == 27000000 || | ||
590 | pdata->refclk_hz == 42000000)); | ||
591 | |||
592 | sys_freq = pdata->refclk_hz / 10000; | ||
593 | i2c_wr8(sd, SYS_FREQ0, sys_freq & 0x00ff); | ||
594 | i2c_wr8(sd, SYS_FREQ1, (sys_freq & 0xff00) >> 8); | ||
595 | |||
596 | i2c_wr8_and_or(sd, PHY_CTL0, ~MASK_PHY_SYSCLK_IND, | ||
597 | (pdata->refclk_hz == 42000000) ? | ||
598 | MASK_PHY_SYSCLK_IND : 0x0); | ||
599 | |||
600 | fh_min = pdata->refclk_hz / 100000; | ||
601 | i2c_wr8(sd, FH_MIN0, fh_min & 0x00ff); | ||
602 | i2c_wr8(sd, FH_MIN1, (fh_min & 0xff00) >> 8); | ||
603 | |||
604 | fh_max = (fh_min * 66) / 10; | ||
605 | i2c_wr8(sd, FH_MAX0, fh_max & 0x00ff); | ||
606 | i2c_wr8(sd, FH_MAX1, (fh_max & 0xff00) >> 8); | ||
607 | |||
608 | lockdet_ref = pdata->refclk_hz / 100; | ||
609 | i2c_wr8(sd, LOCKDET_REF0, lockdet_ref & 0x0000ff); | ||
610 | i2c_wr8(sd, LOCKDET_REF1, (lockdet_ref & 0x00ff00) >> 8); | ||
611 | i2c_wr8(sd, LOCKDET_REF2, (lockdet_ref & 0x0f0000) >> 16); | ||
612 | |||
613 | i2c_wr8_and_or(sd, NCO_F0_MOD, ~MASK_NCO_F0_MOD, | ||
614 | (pdata->refclk_hz == 27000000) ? | ||
615 | MASK_NCO_F0_MOD_27MHZ : 0x0); | ||
616 | } | ||
617 | |||
618 | static void tc358743_set_csi_color_space(struct v4l2_subdev *sd) | ||
619 | { | ||
620 | struct tc358743_state *state = to_state(sd); | ||
621 | |||
622 | switch (state->mbus_fmt_code) { | ||
623 | case MEDIA_BUS_FMT_UYVY8_1X16: | ||
624 | v4l2_dbg(2, debug, sd, "%s: YCbCr 422 16-bit\n", __func__); | ||
625 | i2c_wr8_and_or(sd, VOUT_SET2, | ||
626 | ~(MASK_SEL422 | MASK_VOUT_422FIL_100) & 0xff, | ||
627 | MASK_SEL422 | MASK_VOUT_422FIL_100); | ||
628 | i2c_wr8_and_or(sd, VI_REP, ~MASK_VOUT_COLOR_SEL & 0xff, | ||
629 | MASK_VOUT_COLOR_601_YCBCR_LIMITED); | ||
630 | mutex_lock(&state->confctl_mutex); | ||
631 | i2c_wr16_and_or(sd, CONFCTL, ~MASK_YCBCRFMT, | ||
632 | MASK_YCBCRFMT_422_8_BIT); | ||
633 | mutex_unlock(&state->confctl_mutex); | ||
634 | break; | ||
635 | case MEDIA_BUS_FMT_RGB888_1X24: | ||
636 | v4l2_dbg(2, debug, sd, "%s: RGB 888 24-bit\n", __func__); | ||
637 | i2c_wr8_and_or(sd, VOUT_SET2, | ||
638 | ~(MASK_SEL422 | MASK_VOUT_422FIL_100) & 0xff, | ||
639 | 0x00); | ||
640 | i2c_wr8_and_or(sd, VI_REP, ~MASK_VOUT_COLOR_SEL & 0xff, | ||
641 | MASK_VOUT_COLOR_RGB_FULL); | ||
642 | mutex_lock(&state->confctl_mutex); | ||
643 | i2c_wr16_and_or(sd, CONFCTL, ~MASK_YCBCRFMT, 0); | ||
644 | mutex_unlock(&state->confctl_mutex); | ||
645 | break; | ||
646 | default: | ||
647 | v4l2_dbg(2, debug, sd, "%s: Unsupported format code 0x%x\n", | ||
648 | __func__, state->mbus_fmt_code); | ||
649 | } | ||
650 | } | ||
651 | |||
652 | static unsigned tc358743_num_csi_lanes_needed(struct v4l2_subdev *sd) | ||
653 | { | ||
654 | struct tc358743_state *state = to_state(sd); | ||
655 | struct v4l2_bt_timings *bt = &state->timings.bt; | ||
656 | struct tc358743_platform_data *pdata = &state->pdata; | ||
657 | u32 bits_pr_pixel = | ||
658 | (state->mbus_fmt_code == MEDIA_BUS_FMT_UYVY8_1X16) ? 16 : 24; | ||
659 | u32 bps = bt->width * bt->height * fps(bt) * bits_pr_pixel; | ||
660 | u32 bps_pr_lane = (pdata->refclk_hz / pdata->pll_prd) * pdata->pll_fbd; | ||
661 | |||
662 | return DIV_ROUND_UP(bps, bps_pr_lane); | ||
663 | } | ||
664 | |||
665 | static void tc358743_set_csi(struct v4l2_subdev *sd) | ||
666 | { | ||
667 | struct tc358743_state *state = to_state(sd); | ||
668 | struct tc358743_platform_data *pdata = &state->pdata; | ||
669 | unsigned lanes = tc358743_num_csi_lanes_needed(sd); | ||
670 | |||
671 | v4l2_dbg(3, debug, sd, "%s:\n", __func__); | ||
672 | |||
673 | tc358743_reset(sd, MASK_CTXRST); | ||
674 | |||
675 | if (lanes < 1) | ||
676 | i2c_wr32(sd, CLW_CNTRL, MASK_CLW_LANEDISABLE); | ||
677 | if (lanes < 1) | ||
678 | i2c_wr32(sd, D0W_CNTRL, MASK_D0W_LANEDISABLE); | ||
679 | if (lanes < 2) | ||
680 | i2c_wr32(sd, D1W_CNTRL, MASK_D1W_LANEDISABLE); | ||
681 | if (lanes < 3) | ||
682 | i2c_wr32(sd, D2W_CNTRL, MASK_D2W_LANEDISABLE); | ||
683 | if (lanes < 4) | ||
684 | i2c_wr32(sd, D3W_CNTRL, MASK_D3W_LANEDISABLE); | ||
685 | |||
686 | i2c_wr32(sd, LINEINITCNT, pdata->lineinitcnt); | ||
687 | i2c_wr32(sd, LPTXTIMECNT, pdata->lptxtimecnt); | ||
688 | i2c_wr32(sd, TCLK_HEADERCNT, pdata->tclk_headercnt); | ||
689 | i2c_wr32(sd, TCLK_TRAILCNT, pdata->tclk_trailcnt); | ||
690 | i2c_wr32(sd, THS_HEADERCNT, pdata->ths_headercnt); | ||
691 | i2c_wr32(sd, TWAKEUP, pdata->twakeup); | ||
692 | i2c_wr32(sd, TCLK_POSTCNT, pdata->tclk_postcnt); | ||
693 | i2c_wr32(sd, THS_TRAILCNT, pdata->ths_trailcnt); | ||
694 | i2c_wr32(sd, HSTXVREGCNT, pdata->hstxvregcnt); | ||
695 | |||
696 | i2c_wr32(sd, HSTXVREGEN, | ||
697 | ((lanes > 0) ? MASK_CLM_HSTXVREGEN : 0x0) | | ||
698 | ((lanes > 0) ? MASK_D0M_HSTXVREGEN : 0x0) | | ||
699 | ((lanes > 1) ? MASK_D1M_HSTXVREGEN : 0x0) | | ||
700 | ((lanes > 2) ? MASK_D2M_HSTXVREGEN : 0x0) | | ||
701 | ((lanes > 3) ? MASK_D3M_HSTXVREGEN : 0x0)); | ||
702 | |||
703 | i2c_wr32(sd, TXOPTIONCNTRL, MASK_CONTCLKMODE); | ||
704 | i2c_wr32(sd, STARTCNTRL, MASK_START); | ||
705 | i2c_wr32(sd, CSI_START, MASK_STRT); | ||
706 | |||
707 | i2c_wr32(sd, CSI_CONFW, MASK_MODE_SET | | ||
708 | MASK_ADDRESS_CSI_CONTROL | | ||
709 | MASK_CSI_MODE | | ||
710 | MASK_TXHSMD | | ||
711 | ((lanes == 4) ? MASK_NOL_4 : | ||
712 | (lanes == 3) ? MASK_NOL_3 : | ||
713 | (lanes == 2) ? MASK_NOL_2 : MASK_NOL_1)); | ||
714 | |||
715 | i2c_wr32(sd, CSI_CONFW, MASK_MODE_SET | | ||
716 | MASK_ADDRESS_CSI_ERR_INTENA | MASK_TXBRK | MASK_QUNK | | ||
717 | MASK_WCER | MASK_INER); | ||
718 | |||
719 | i2c_wr32(sd, CSI_CONFW, MASK_MODE_CLEAR | | ||
720 | MASK_ADDRESS_CSI_ERR_HALT | MASK_TXBRK | MASK_QUNK); | ||
721 | |||
722 | i2c_wr32(sd, CSI_CONFW, MASK_MODE_SET | | ||
723 | MASK_ADDRESS_CSI_INT_ENA | MASK_INTER); | ||
724 | } | ||
725 | |||
726 | static void tc358743_set_hdmi_phy(struct v4l2_subdev *sd) | ||
727 | { | ||
728 | struct tc358743_state *state = to_state(sd); | ||
729 | struct tc358743_platform_data *pdata = &state->pdata; | ||
730 | |||
731 | /* Default settings from REF_02, sheet "Source HDMI" | ||
732 | * and custom settings as platform data */ | ||
733 | i2c_wr8_and_or(sd, PHY_EN, ~MASK_ENABLE_PHY, 0x0); | ||
734 | i2c_wr8(sd, PHY_CTL1, SET_PHY_AUTO_RST1_US(1600) | | ||
735 | SET_FREQ_RANGE_MODE_CYCLES(1)); | ||
736 | i2c_wr8_and_or(sd, PHY_CTL2, ~MASK_PHY_AUTO_RSTn, | ||
737 | (pdata->hdmi_phy_auto_reset_tmds_detected ? | ||
738 | MASK_PHY_AUTO_RST2 : 0) | | ||
739 | (pdata->hdmi_phy_auto_reset_tmds_in_range ? | ||
740 | MASK_PHY_AUTO_RST3 : 0) | | ||
741 | (pdata->hdmi_phy_auto_reset_tmds_valid ? | ||
742 | MASK_PHY_AUTO_RST4 : 0)); | ||
743 | i2c_wr8(sd, PHY_BIAS, 0x40); | ||
744 | i2c_wr8(sd, PHY_CSQ, SET_CSQ_CNT_LEVEL(0x0a)); | ||
745 | i2c_wr8(sd, AVM_CTL, 45); | ||
746 | i2c_wr8_and_or(sd, HDMI_DET, ~MASK_HDMI_DET_V, | ||
747 | pdata->hdmi_detection_delay << 4); | ||
748 | i2c_wr8_and_or(sd, HV_RST, ~(MASK_H_PI_RST | MASK_V_PI_RST), | ||
749 | (pdata->hdmi_phy_auto_reset_hsync_out_of_range ? | ||
750 | MASK_H_PI_RST : 0) | | ||
751 | (pdata->hdmi_phy_auto_reset_vsync_out_of_range ? | ||
752 | MASK_V_PI_RST : 0)); | ||
753 | i2c_wr8_and_or(sd, PHY_EN, ~MASK_ENABLE_PHY, MASK_ENABLE_PHY); | ||
754 | } | ||
755 | |||
756 | static void tc358743_set_hdmi_audio(struct v4l2_subdev *sd) | ||
757 | { | ||
758 | struct tc358743_state *state = to_state(sd); | ||
759 | |||
760 | /* Default settings from REF_02, sheet "Source HDMI" */ | ||
761 | i2c_wr8(sd, FORCE_MUTE, 0x00); | ||
762 | i2c_wr8(sd, AUTO_CMD0, MASK_AUTO_MUTE7 | MASK_AUTO_MUTE6 | | ||
763 | MASK_AUTO_MUTE5 | MASK_AUTO_MUTE4 | | ||
764 | MASK_AUTO_MUTE1 | MASK_AUTO_MUTE0); | ||
765 | i2c_wr8(sd, AUTO_CMD1, MASK_AUTO_MUTE9); | ||
766 | i2c_wr8(sd, AUTO_CMD2, MASK_AUTO_PLAY3 | MASK_AUTO_PLAY2); | ||
767 | i2c_wr8(sd, BUFINIT_START, SET_BUFINIT_START_MS(500)); | ||
768 | i2c_wr8(sd, FS_MUTE, 0x00); | ||
769 | i2c_wr8(sd, FS_IMODE, MASK_NLPCM_SMODE | MASK_FS_SMODE); | ||
770 | i2c_wr8(sd, ACR_MODE, MASK_CTS_MODE); | ||
771 | i2c_wr8(sd, ACR_MDF0, MASK_ACR_L2MDF_1976_PPM | MASK_ACR_L1MDF_976_PPM); | ||
772 | i2c_wr8(sd, ACR_MDF1, MASK_ACR_L3MDF_3906_PPM); | ||
773 | i2c_wr8(sd, SDO_MODE1, MASK_SDO_FMT_I2S); | ||
774 | i2c_wr8(sd, DIV_MODE, SET_DIV_DLY_MS(100)); | ||
775 | |||
776 | mutex_lock(&state->confctl_mutex); | ||
777 | i2c_wr16_and_or(sd, CONFCTL, 0xffff, MASK_AUDCHNUM_2 | | ||
778 | MASK_AUDOUTSEL_I2S | MASK_AUTOINDEX); | ||
779 | mutex_unlock(&state->confctl_mutex); | ||
780 | } | ||
781 | |||
782 | static void tc358743_set_hdmi_info_frame_mode(struct v4l2_subdev *sd) | ||
783 | { | ||
784 | /* Default settings from REF_02, sheet "Source HDMI" */ | ||
785 | i2c_wr8(sd, PK_INT_MODE, MASK_ISRC2_INT_MODE | MASK_ISRC_INT_MODE | | ||
786 | MASK_ACP_INT_MODE | MASK_VS_INT_MODE | | ||
787 | MASK_SPD_INT_MODE | MASK_MS_INT_MODE | | ||
788 | MASK_AUD_INT_MODE | MASK_AVI_INT_MODE); | ||
789 | i2c_wr8(sd, NO_PKT_LIMIT, 0x2c); | ||
790 | i2c_wr8(sd, NO_PKT_CLR, 0x53); | ||
791 | i2c_wr8(sd, ERR_PK_LIMIT, 0x01); | ||
792 | i2c_wr8(sd, NO_PKT_LIMIT2, 0x30); | ||
793 | i2c_wr8(sd, NO_GDB_LIMIT, 0x10); | ||
794 | } | ||
795 | |||
796 | static void tc358743_initial_setup(struct v4l2_subdev *sd) | ||
797 | { | ||
798 | struct tc358743_state *state = to_state(sd); | ||
799 | struct tc358743_platform_data *pdata = &state->pdata; | ||
800 | |||
801 | /* CEC and IR are not supported by this driver */ | ||
802 | i2c_wr16_and_or(sd, SYSCTL, ~(MASK_CECRST | MASK_IRRST), | ||
803 | (MASK_CECRST | MASK_IRRST)); | ||
804 | |||
805 | tc358743_reset(sd, MASK_CTXRST | MASK_HDMIRST); | ||
806 | tc358743_sleep_mode(sd, false); | ||
807 | |||
808 | i2c_wr16(sd, FIFOCTL, pdata->fifo_level); | ||
809 | |||
810 | tc358743_set_ref_clk(sd); | ||
811 | |||
812 | i2c_wr8_and_or(sd, DDC_CTL, ~MASK_DDC5V_MODE, | ||
813 | pdata->ddc5v_delay & MASK_DDC5V_MODE); | ||
814 | i2c_wr8_and_or(sd, EDID_MODE, ~MASK_EDID_MODE, MASK_EDID_MODE_E_DDC); | ||
815 | |||
816 | tc358743_set_hdmi_phy(sd); | ||
817 | tc358743_set_hdmi_hdcp(sd, pdata->enable_hdcp); | ||
818 | tc358743_set_hdmi_audio(sd); | ||
819 | tc358743_set_hdmi_info_frame_mode(sd); | ||
820 | |||
821 | /* All CE and IT formats are detected as RGB full range in DVI mode */ | ||
822 | i2c_wr8_and_or(sd, VI_MODE, ~MASK_RGB_DVI, 0); | ||
823 | |||
824 | i2c_wr8_and_or(sd, VOUT_SET2, ~MASK_VOUTCOLORMODE, | ||
825 | MASK_VOUTCOLORMODE_AUTO); | ||
826 | i2c_wr8(sd, VOUT_SET3, MASK_VOUT_EXTCNT); | ||
827 | } | ||
828 | |||
829 | /* --------------- IRQ --------------- */ | ||
830 | |||
831 | static void tc358743_format_change(struct v4l2_subdev *sd) | ||
832 | { | ||
833 | struct tc358743_state *state = to_state(sd); | ||
834 | struct v4l2_dv_timings timings; | ||
835 | const struct v4l2_event tc358743_ev_fmt = { | ||
836 | .type = V4L2_EVENT_SOURCE_CHANGE, | ||
837 | .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, | ||
838 | }; | ||
839 | |||
840 | if (tc358743_get_detected_timings(sd, &timings)) { | ||
841 | enable_stream(sd, false); | ||
842 | |||
843 | v4l2_dbg(1, debug, sd, "%s: Format changed. No signal\n", | ||
844 | __func__); | ||
845 | } else { | ||
846 | if (!v4l2_match_dv_timings(&state->timings, &timings, 0)) | ||
847 | enable_stream(sd, false); | ||
848 | |||
849 | v4l2_print_dv_timings(sd->name, | ||
850 | "tc358743_format_change: Format changed. New format: ", | ||
851 | &timings, false); | ||
852 | } | ||
853 | |||
854 | v4l2_subdev_notify(sd, V4L2_DEVICE_NOTIFY_EVENT, | ||
855 | (void *)&tc358743_ev_fmt); | ||
856 | } | ||
857 | |||
858 | static void tc358743_init_interrupts(struct v4l2_subdev *sd) | ||
859 | { | ||
860 | u16 i; | ||
861 | |||
862 | /* clear interrupt status registers */ | ||
863 | for (i = SYS_INT; i <= KEY_INT; i++) | ||
864 | i2c_wr8(sd, i, 0xff); | ||
865 | |||
866 | i2c_wr16(sd, INTSTATUS, 0xffff); | ||
867 | } | ||
868 | |||
869 | static void tc358743_enable_interrupts(struct v4l2_subdev *sd, | ||
870 | bool cable_connected) | ||
871 | { | ||
872 | v4l2_dbg(2, debug, sd, "%s: cable connected = %d\n", __func__, | ||
873 | cable_connected); | ||
874 | |||
875 | if (cable_connected) { | ||
876 | i2c_wr8(sd, SYS_INTM, ~(MASK_M_DDC | MASK_M_DVI_DET | | ||
877 | MASK_M_HDMI_DET) & 0xff); | ||
878 | i2c_wr8(sd, CLK_INTM, ~MASK_M_IN_DE_CHG); | ||
879 | i2c_wr8(sd, CBIT_INTM, ~(MASK_M_CBIT_FS | MASK_M_AF_LOCK | | ||
880 | MASK_M_AF_UNLOCK) & 0xff); | ||
881 | i2c_wr8(sd, AUDIO_INTM, ~MASK_M_BUFINIT_END); | ||
882 | i2c_wr8(sd, MISC_INTM, ~MASK_M_SYNC_CHG); | ||
883 | } else { | ||
884 | i2c_wr8(sd, SYS_INTM, ~MASK_M_DDC & 0xff); | ||
885 | i2c_wr8(sd, CLK_INTM, 0xff); | ||
886 | i2c_wr8(sd, CBIT_INTM, 0xff); | ||
887 | i2c_wr8(sd, AUDIO_INTM, 0xff); | ||
888 | i2c_wr8(sd, MISC_INTM, 0xff); | ||
889 | } | ||
890 | } | ||
891 | |||
892 | static void tc358743_hdmi_audio_int_handler(struct v4l2_subdev *sd, | ||
893 | bool *handled) | ||
894 | { | ||
895 | u8 audio_int_mask = i2c_rd8(sd, AUDIO_INTM); | ||
896 | u8 audio_int = i2c_rd8(sd, AUDIO_INT) & ~audio_int_mask; | ||
897 | |||
898 | i2c_wr8(sd, AUDIO_INT, audio_int); | ||
899 | |||
900 | v4l2_dbg(3, debug, sd, "%s: AUDIO_INT = 0x%02x\n", __func__, audio_int); | ||
901 | |||
902 | tc358743_s_ctrl_audio_sampling_rate(sd); | ||
903 | tc358743_s_ctrl_audio_present(sd); | ||
904 | } | ||
905 | |||
906 | static void tc358743_csi_err_int_handler(struct v4l2_subdev *sd, bool *handled) | ||
907 | { | ||
908 | v4l2_err(sd, "%s: CSI_ERR = 0x%x\n", __func__, i2c_rd32(sd, CSI_ERR)); | ||
909 | |||
910 | i2c_wr32(sd, CSI_INT_CLR, MASK_ICRER); | ||
911 | } | ||
912 | |||
913 | static void tc358743_hdmi_misc_int_handler(struct v4l2_subdev *sd, | ||
914 | bool *handled) | ||
915 | { | ||
916 | u8 misc_int_mask = i2c_rd8(sd, MISC_INTM); | ||
917 | u8 misc_int = i2c_rd8(sd, MISC_INT) & ~misc_int_mask; | ||
918 | |||
919 | i2c_wr8(sd, MISC_INT, misc_int); | ||
920 | |||
921 | v4l2_dbg(3, debug, sd, "%s: MISC_INT = 0x%02x\n", __func__, misc_int); | ||
922 | |||
923 | if (misc_int & MASK_I_SYNC_CHG) { | ||
924 | /* Reset the HDMI PHY to try to trigger proper lock on the | ||
925 | * incoming video format. Erase BKSV to prevent that old keys | ||
926 | * are used when a new source is connected. */ | ||
927 | if (no_sync(sd) || no_signal(sd)) { | ||
928 | tc358743_reset_phy(sd); | ||
929 | tc358743_erase_bksv(sd); | ||
930 | } | ||
931 | |||
932 | tc358743_format_change(sd); | ||
933 | |||
934 | misc_int &= ~MASK_I_SYNC_CHG; | ||
935 | if (handled) | ||
936 | *handled = true; | ||
937 | } | ||
938 | |||
939 | if (misc_int) { | ||
940 | v4l2_err(sd, "%s: Unhandled MISC_INT interrupts: 0x%02x\n", | ||
941 | __func__, misc_int); | ||
942 | } | ||
943 | } | ||
944 | |||
945 | static void tc358743_hdmi_cbit_int_handler(struct v4l2_subdev *sd, | ||
946 | bool *handled) | ||
947 | { | ||
948 | u8 cbit_int_mask = i2c_rd8(sd, CBIT_INTM); | ||
949 | u8 cbit_int = i2c_rd8(sd, CBIT_INT) & ~cbit_int_mask; | ||
950 | |||
951 | i2c_wr8(sd, CBIT_INT, cbit_int); | ||
952 | |||
953 | v4l2_dbg(3, debug, sd, "%s: CBIT_INT = 0x%02x\n", __func__, cbit_int); | ||
954 | |||
955 | if (cbit_int & MASK_I_CBIT_FS) { | ||
956 | |||
957 | v4l2_dbg(1, debug, sd, "%s: Audio sample rate changed\n", | ||
958 | __func__); | ||
959 | tc358743_s_ctrl_audio_sampling_rate(sd); | ||
960 | |||
961 | cbit_int &= ~MASK_I_CBIT_FS; | ||
962 | if (handled) | ||
963 | *handled = true; | ||
964 | } | ||
965 | |||
966 | if (cbit_int & (MASK_I_AF_LOCK | MASK_I_AF_UNLOCK)) { | ||
967 | |||
968 | v4l2_dbg(1, debug, sd, "%s: Audio present changed\n", | ||
969 | __func__); | ||
970 | tc358743_s_ctrl_audio_present(sd); | ||
971 | |||
972 | cbit_int &= ~(MASK_I_AF_LOCK | MASK_I_AF_UNLOCK); | ||
973 | if (handled) | ||
974 | *handled = true; | ||
975 | } | ||
976 | |||
977 | if (cbit_int) { | ||
978 | v4l2_err(sd, "%s: Unhandled CBIT_INT interrupts: 0x%02x\n", | ||
979 | __func__, cbit_int); | ||
980 | } | ||
981 | } | ||
982 | |||
983 | static void tc358743_hdmi_clk_int_handler(struct v4l2_subdev *sd, bool *handled) | ||
984 | { | ||
985 | u8 clk_int_mask = i2c_rd8(sd, CLK_INTM); | ||
986 | u8 clk_int = i2c_rd8(sd, CLK_INT) & ~clk_int_mask; | ||
987 | |||
988 | /* Bit 7 and bit 6 are set even when they are masked */ | ||
989 | i2c_wr8(sd, CLK_INT, clk_int | 0x80 | MASK_I_OUT_H_CHG); | ||
990 | |||
991 | v4l2_dbg(3, debug, sd, "%s: CLK_INT = 0x%02x\n", __func__, clk_int); | ||
992 | |||
993 | if (clk_int & (MASK_I_IN_DE_CHG)) { | ||
994 | |||
995 | v4l2_dbg(1, debug, sd, "%s: DE size or position has changed\n", | ||
996 | __func__); | ||
997 | |||
998 | /* If the source switch to a new resolution with the same pixel | ||
999 | * frequency as the existing (e.g. 1080p25 -> 720p50), the | ||
1000 | * I_SYNC_CHG interrupt is not always triggered, while the | ||
1001 | * I_IN_DE_CHG interrupt seems to work fine. Format change | ||
1002 | * notifications are only sent when the signal is stable to | ||
1003 | * reduce the number of notifications. */ | ||
1004 | if (!no_signal(sd) && !no_sync(sd)) | ||
1005 | tc358743_format_change(sd); | ||
1006 | |||
1007 | clk_int &= ~(MASK_I_IN_DE_CHG); | ||
1008 | if (handled) | ||
1009 | *handled = true; | ||
1010 | } | ||
1011 | |||
1012 | if (clk_int) { | ||
1013 | v4l2_err(sd, "%s: Unhandled CLK_INT interrupts: 0x%02x\n", | ||
1014 | __func__, clk_int); | ||
1015 | } | ||
1016 | } | ||
1017 | |||
1018 | static void tc358743_hdmi_sys_int_handler(struct v4l2_subdev *sd, bool *handled) | ||
1019 | { | ||
1020 | struct tc358743_state *state = to_state(sd); | ||
1021 | u8 sys_int_mask = i2c_rd8(sd, SYS_INTM); | ||
1022 | u8 sys_int = i2c_rd8(sd, SYS_INT) & ~sys_int_mask; | ||
1023 | |||
1024 | i2c_wr8(sd, SYS_INT, sys_int); | ||
1025 | |||
1026 | v4l2_dbg(3, debug, sd, "%s: SYS_INT = 0x%02x\n", __func__, sys_int); | ||
1027 | |||
1028 | if (sys_int & MASK_I_DDC) { | ||
1029 | bool tx_5v = tx_5v_power_present(sd); | ||
1030 | |||
1031 | v4l2_dbg(1, debug, sd, "%s: Tx 5V power present: %s\n", | ||
1032 | __func__, tx_5v ? "yes" : "no"); | ||
1033 | |||
1034 | if (tx_5v) { | ||
1035 | tc358743_enable_edid(sd); | ||
1036 | } else { | ||
1037 | tc358743_enable_interrupts(sd, false); | ||
1038 | tc358743_disable_edid(sd); | ||
1039 | memset(&state->timings, 0, sizeof(state->timings)); | ||
1040 | tc358743_erase_bksv(sd); | ||
1041 | tc358743_update_controls(sd); | ||
1042 | } | ||
1043 | |||
1044 | sys_int &= ~MASK_I_DDC; | ||
1045 | if (handled) | ||
1046 | *handled = true; | ||
1047 | } | ||
1048 | |||
1049 | if (sys_int & MASK_I_DVI) { | ||
1050 | v4l2_dbg(1, debug, sd, "%s: HDMI->DVI change detected\n", | ||
1051 | __func__); | ||
1052 | |||
1053 | /* Reset the HDMI PHY to try to trigger proper lock on the | ||
1054 | * incoming video format. Erase BKSV to prevent that old keys | ||
1055 | * are used when a new source is connected. */ | ||
1056 | if (no_sync(sd) || no_signal(sd)) { | ||
1057 | tc358743_reset_phy(sd); | ||
1058 | tc358743_erase_bksv(sd); | ||
1059 | } | ||
1060 | |||
1061 | sys_int &= ~MASK_I_DVI; | ||
1062 | if (handled) | ||
1063 | *handled = true; | ||
1064 | } | ||
1065 | |||
1066 | if (sys_int & MASK_I_HDMI) { | ||
1067 | v4l2_dbg(1, debug, sd, "%s: DVI->HDMI change detected\n", | ||
1068 | __func__); | ||
1069 | |||
1070 | /* Register is reset in DVI mode (REF_01, c. 6.6.41) */ | ||
1071 | i2c_wr8(sd, ANA_CTL, MASK_APPL_PCSX_NORMAL | MASK_ANALOG_ON); | ||
1072 | |||
1073 | sys_int &= ~MASK_I_HDMI; | ||
1074 | if (handled) | ||
1075 | *handled = true; | ||
1076 | } | ||
1077 | |||
1078 | if (sys_int) { | ||
1079 | v4l2_err(sd, "%s: Unhandled SYS_INT interrupts: 0x%02x\n", | ||
1080 | __func__, sys_int); | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | /* --------------- CORE OPS --------------- */ | ||
1085 | |||
1086 | static int tc358743_log_status(struct v4l2_subdev *sd) | ||
1087 | { | ||
1088 | struct tc358743_state *state = to_state(sd); | ||
1089 | struct v4l2_dv_timings timings; | ||
1090 | uint8_t hdmi_sys_status = i2c_rd8(sd, SYS_STATUS); | ||
1091 | uint16_t sysctl = i2c_rd16(sd, SYSCTL); | ||
1092 | u8 vi_status3 = i2c_rd8(sd, VI_STATUS3); | ||
1093 | const int deep_color_mode[4] = { 8, 10, 12, 16 }; | ||
1094 | static const char * const input_color_space[] = { | ||
1095 | "RGB", "YCbCr 601", "Adobe RGB", "YCbCr 709", "NA (4)", | ||
1096 | "xvYCC 601", "NA(6)", "xvYCC 709", "NA(8)", "sYCC601", | ||
1097 | "NA(10)", "NA(11)", "NA(12)", "Adobe YCC 601"}; | ||
1098 | |||
1099 | v4l2_info(sd, "-----Chip status-----\n"); | ||
1100 | v4l2_info(sd, "Chip ID: 0x%02x\n", | ||
1101 | (i2c_rd16(sd, CHIPID) & MASK_CHIPID) >> 8); | ||
1102 | v4l2_info(sd, "Chip revision: 0x%02x\n", | ||
1103 | i2c_rd16(sd, CHIPID) & MASK_REVID); | ||
1104 | v4l2_info(sd, "Reset: IR: %d, CEC: %d, CSI TX: %d, HDMI: %d\n", | ||
1105 | !!(sysctl & MASK_IRRST), | ||
1106 | !!(sysctl & MASK_CECRST), | ||
1107 | !!(sysctl & MASK_CTXRST), | ||
1108 | !!(sysctl & MASK_HDMIRST)); | ||
1109 | v4l2_info(sd, "Sleep mode: %s\n", sysctl & MASK_SLEEP ? "on" : "off"); | ||
1110 | v4l2_info(sd, "Cable detected (+5V power): %s\n", | ||
1111 | hdmi_sys_status & MASK_S_DDC5V ? "yes" : "no"); | ||
1112 | v4l2_info(sd, "DDC lines enabled: %s\n", | ||
1113 | (i2c_rd8(sd, EDID_MODE) & MASK_EDID_MODE_E_DDC) ? | ||
1114 | "yes" : "no"); | ||
1115 | v4l2_info(sd, "Hotplug enabled: %s\n", | ||
1116 | (i2c_rd8(sd, HPD_CTL) & MASK_HPD_OUT0) ? | ||
1117 | "yes" : "no"); | ||
1118 | v4l2_info(sd, "CEC enabled: %s\n", | ||
1119 | (i2c_rd16(sd, CECEN) & MASK_CECEN) ? "yes" : "no"); | ||
1120 | v4l2_info(sd, "-----Signal status-----\n"); | ||
1121 | v4l2_info(sd, "TMDS signal detected: %s\n", | ||
1122 | hdmi_sys_status & MASK_S_TMDS ? "yes" : "no"); | ||
1123 | v4l2_info(sd, "Stable sync signal: %s\n", | ||
1124 | hdmi_sys_status & MASK_S_SYNC ? "yes" : "no"); | ||
1125 | v4l2_info(sd, "PHY PLL locked: %s\n", | ||
1126 | hdmi_sys_status & MASK_S_PHY_PLL ? "yes" : "no"); | ||
1127 | v4l2_info(sd, "PHY DE detected: %s\n", | ||
1128 | hdmi_sys_status & MASK_S_PHY_SCDT ? "yes" : "no"); | ||
1129 | |||
1130 | if (tc358743_get_detected_timings(sd, &timings)) { | ||
1131 | v4l2_info(sd, "No video detected\n"); | ||
1132 | } else { | ||
1133 | v4l2_print_dv_timings(sd->name, "Detected format: ", &timings, | ||
1134 | true); | ||
1135 | } | ||
1136 | v4l2_print_dv_timings(sd->name, "Configured format: ", &state->timings, | ||
1137 | true); | ||
1138 | |||
1139 | v4l2_info(sd, "-----CSI-TX status-----\n"); | ||
1140 | v4l2_info(sd, "Lanes needed: %d\n", | ||
1141 | tc358743_num_csi_lanes_needed(sd)); | ||
1142 | v4l2_info(sd, "Lanes in use: %d\n", | ||
1143 | tc358743_num_csi_lanes_in_use(sd)); | ||
1144 | v4l2_info(sd, "Waiting for particular sync signal: %s\n", | ||
1145 | (i2c_rd16(sd, CSI_STATUS) & MASK_S_WSYNC) ? | ||
1146 | "yes" : "no"); | ||
1147 | v4l2_info(sd, "Transmit mode: %s\n", | ||
1148 | (i2c_rd16(sd, CSI_STATUS) & MASK_S_TXACT) ? | ||
1149 | "yes" : "no"); | ||
1150 | v4l2_info(sd, "Receive mode: %s\n", | ||
1151 | (i2c_rd16(sd, CSI_STATUS) & MASK_S_RXACT) ? | ||
1152 | "yes" : "no"); | ||
1153 | v4l2_info(sd, "Stopped: %s\n", | ||
1154 | (i2c_rd16(sd, CSI_STATUS) & MASK_S_HLT) ? | ||
1155 | "yes" : "no"); | ||
1156 | v4l2_info(sd, "Color space: %s\n", | ||
1157 | state->mbus_fmt_code == MEDIA_BUS_FMT_UYVY8_1X16 ? | ||
1158 | "YCbCr 422 16-bit" : | ||
1159 | state->mbus_fmt_code == MEDIA_BUS_FMT_RGB888_1X24 ? | ||
1160 | "RGB 888 24-bit" : "Unsupported"); | ||
1161 | |||
1162 | v4l2_info(sd, "-----%s status-----\n", is_hdmi(sd) ? "HDMI" : "DVI-D"); | ||
1163 | v4l2_info(sd, "HDCP encrypted content: %s\n", | ||
1164 | hdmi_sys_status & MASK_S_HDCP ? "yes" : "no"); | ||
1165 | v4l2_info(sd, "Input color space: %s %s range\n", | ||
1166 | input_color_space[(vi_status3 & MASK_S_V_COLOR) >> 1], | ||
1167 | (vi_status3 & MASK_LIMITED) ? "limited" : "full"); | ||
1168 | if (!is_hdmi(sd)) | ||
1169 | return 0; | ||
1170 | v4l2_info(sd, "AV Mute: %s\n", hdmi_sys_status & MASK_S_AVMUTE ? "on" : | ||
1171 | "off"); | ||
1172 | v4l2_info(sd, "Deep color mode: %d-bits per channel\n", | ||
1173 | deep_color_mode[(i2c_rd8(sd, VI_STATUS1) & | ||
1174 | MASK_S_DEEPCOLOR) >> 2]); | ||
1175 | print_avi_infoframe(sd); | ||
1176 | |||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1181 | static void tc358743_print_register_map(struct v4l2_subdev *sd) | ||
1182 | { | ||
1183 | v4l2_info(sd, "0x0000–0x00FF: Global Control Register\n"); | ||
1184 | v4l2_info(sd, "0x0100–0x01FF: CSI2-TX PHY Register\n"); | ||
1185 | v4l2_info(sd, "0x0200–0x03FF: CSI2-TX PPI Register\n"); | ||
1186 | v4l2_info(sd, "0x0400–0x05FF: Reserved\n"); | ||
1187 | v4l2_info(sd, "0x0600–0x06FF: CEC Register\n"); | ||
1188 | v4l2_info(sd, "0x0700–0x84FF: Reserved\n"); | ||
1189 | v4l2_info(sd, "0x8500–0x85FF: HDMIRX System Control Register\n"); | ||
1190 | v4l2_info(sd, "0x8600–0x86FF: HDMIRX Audio Control Register\n"); | ||
1191 | v4l2_info(sd, "0x8700–0x87FF: HDMIRX InfoFrame packet data Register\n"); | ||
1192 | v4l2_info(sd, "0x8800–0x88FF: HDMIRX HDCP Port Register\n"); | ||
1193 | v4l2_info(sd, "0x8900–0x89FF: HDMIRX Video Output Port & 3D Register\n"); | ||
1194 | v4l2_info(sd, "0x8A00–0x8BFF: Reserved\n"); | ||
1195 | v4l2_info(sd, "0x8C00–0x8FFF: HDMIRX EDID-RAM (1024bytes)\n"); | ||
1196 | v4l2_info(sd, "0x9000–0x90FF: HDMIRX GBD Extraction Control\n"); | ||
1197 | v4l2_info(sd, "0x9100–0x92FF: HDMIRX GBD RAM read\n"); | ||
1198 | v4l2_info(sd, "0x9300- : Reserved\n"); | ||
1199 | } | ||
1200 | |||
1201 | static int tc358743_get_reg_size(u16 address) | ||
1202 | { | ||
1203 | /* REF_01 p. 66-72 */ | ||
1204 | if (address <= 0x00ff) | ||
1205 | return 2; | ||
1206 | else if ((address >= 0x0100) && (address <= 0x06FF)) | ||
1207 | return 4; | ||
1208 | else if ((address >= 0x0700) && (address <= 0x84ff)) | ||
1209 | return 2; | ||
1210 | else | ||
1211 | return 1; | ||
1212 | } | ||
1213 | |||
1214 | static int tc358743_g_register(struct v4l2_subdev *sd, | ||
1215 | struct v4l2_dbg_register *reg) | ||
1216 | { | ||
1217 | if (reg->reg > 0xffff) { | ||
1218 | tc358743_print_register_map(sd); | ||
1219 | return -EINVAL; | ||
1220 | } | ||
1221 | |||
1222 | reg->size = tc358743_get_reg_size(reg->reg); | ||
1223 | |||
1224 | i2c_rd(sd, reg->reg, (u8 *)®->val, reg->size); | ||
1225 | |||
1226 | return 0; | ||
1227 | } | ||
1228 | |||
1229 | static int tc358743_s_register(struct v4l2_subdev *sd, | ||
1230 | const struct v4l2_dbg_register *reg) | ||
1231 | { | ||
1232 | if (reg->reg > 0xffff) { | ||
1233 | tc358743_print_register_map(sd); | ||
1234 | return -EINVAL; | ||
1235 | } | ||
1236 | |||
1237 | /* It should not be possible for the user to enable HDCP with a simple | ||
1238 | * v4l2-dbg command. | ||
1239 | * | ||
1240 | * DO NOT REMOVE THIS unless all other issues with HDCP have been | ||
1241 | * resolved. | ||
1242 | */ | ||
1243 | if (reg->reg == HDCP_MODE || | ||
1244 | reg->reg == HDCP_REG1 || | ||
1245 | reg->reg == HDCP_REG2 || | ||
1246 | reg->reg == HDCP_REG3 || | ||
1247 | reg->reg == BCAPS) | ||
1248 | return 0; | ||
1249 | |||
1250 | i2c_wr(sd, (u16)reg->reg, (u8 *)®->val, | ||
1251 | tc358743_get_reg_size(reg->reg)); | ||
1252 | |||
1253 | return 0; | ||
1254 | } | ||
1255 | #endif | ||
1256 | |||
1257 | static int tc358743_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | ||
1258 | { | ||
1259 | u16 intstatus = i2c_rd16(sd, INTSTATUS); | ||
1260 | |||
1261 | v4l2_dbg(1, debug, sd, "%s: IntStatus = 0x%04x\n", __func__, intstatus); | ||
1262 | |||
1263 | if (intstatus & MASK_HDMI_INT) { | ||
1264 | u8 hdmi_int0 = i2c_rd8(sd, HDMI_INT0); | ||
1265 | u8 hdmi_int1 = i2c_rd8(sd, HDMI_INT1); | ||
1266 | |||
1267 | if (hdmi_int0 & MASK_I_MISC) | ||
1268 | tc358743_hdmi_misc_int_handler(sd, handled); | ||
1269 | if (hdmi_int1 & MASK_I_CBIT) | ||
1270 | tc358743_hdmi_cbit_int_handler(sd, handled); | ||
1271 | if (hdmi_int1 & MASK_I_CLK) | ||
1272 | tc358743_hdmi_clk_int_handler(sd, handled); | ||
1273 | if (hdmi_int1 & MASK_I_SYS) | ||
1274 | tc358743_hdmi_sys_int_handler(sd, handled); | ||
1275 | if (hdmi_int1 & MASK_I_AUD) | ||
1276 | tc358743_hdmi_audio_int_handler(sd, handled); | ||
1277 | |||
1278 | i2c_wr16(sd, INTSTATUS, MASK_HDMI_INT); | ||
1279 | intstatus &= ~MASK_HDMI_INT; | ||
1280 | } | ||
1281 | |||
1282 | if (intstatus & MASK_CSI_INT) { | ||
1283 | u32 csi_int = i2c_rd32(sd, CSI_INT); | ||
1284 | |||
1285 | if (csi_int & MASK_INTER) | ||
1286 | tc358743_csi_err_int_handler(sd, handled); | ||
1287 | |||
1288 | i2c_wr16(sd, INTSTATUS, MASK_CSI_INT); | ||
1289 | intstatus &= ~MASK_CSI_INT; | ||
1290 | } | ||
1291 | |||
1292 | intstatus = i2c_rd16(sd, INTSTATUS); | ||
1293 | if (intstatus) { | ||
1294 | v4l2_dbg(1, debug, sd, | ||
1295 | "%s: Unhandled IntStatus interrupts: 0x%02x\n", | ||
1296 | __func__, intstatus); | ||
1297 | } | ||
1298 | |||
1299 | return 0; | ||
1300 | } | ||
1301 | |||
1302 | /* --------------- VIDEO OPS --------------- */ | ||
1303 | |||
1304 | static int tc358743_g_input_status(struct v4l2_subdev *sd, u32 *status) | ||
1305 | { | ||
1306 | *status = 0; | ||
1307 | *status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0; | ||
1308 | *status |= no_sync(sd) ? V4L2_IN_ST_NO_SYNC : 0; | ||
1309 | |||
1310 | v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status); | ||
1311 | |||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | static int tc358743_s_dv_timings(struct v4l2_subdev *sd, | ||
1316 | struct v4l2_dv_timings *timings) | ||
1317 | { | ||
1318 | struct tc358743_state *state = to_state(sd); | ||
1319 | struct v4l2_bt_timings *bt; | ||
1320 | |||
1321 | if (!timings) | ||
1322 | return -EINVAL; | ||
1323 | |||
1324 | if (debug) | ||
1325 | v4l2_print_dv_timings(sd->name, "tc358743_s_dv_timings: ", | ||
1326 | timings, false); | ||
1327 | |||
1328 | if (v4l2_match_dv_timings(&state->timings, timings, 0)) { | ||
1329 | v4l2_dbg(1, debug, sd, "%s: no change\n", __func__); | ||
1330 | return 0; | ||
1331 | } | ||
1332 | |||
1333 | bt = &timings->bt; | ||
1334 | |||
1335 | if (!v4l2_valid_dv_timings(timings, | ||
1336 | &tc358743_timings_cap, NULL, NULL)) { | ||
1337 | v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__); | ||
1338 | return -ERANGE; | ||
1339 | } | ||
1340 | |||
1341 | state->timings = *timings; | ||
1342 | |||
1343 | enable_stream(sd, false); | ||
1344 | tc358743_set_pll(sd); | ||
1345 | tc358743_set_csi(sd); | ||
1346 | |||
1347 | return 0; | ||
1348 | } | ||
1349 | |||
1350 | static int tc358743_g_dv_timings(struct v4l2_subdev *sd, | ||
1351 | struct v4l2_dv_timings *timings) | ||
1352 | { | ||
1353 | struct tc358743_state *state = to_state(sd); | ||
1354 | |||
1355 | *timings = state->timings; | ||
1356 | |||
1357 | return 0; | ||
1358 | } | ||
1359 | |||
1360 | static int tc358743_enum_dv_timings(struct v4l2_subdev *sd, | ||
1361 | struct v4l2_enum_dv_timings *timings) | ||
1362 | { | ||
1363 | if (timings->pad != 0) | ||
1364 | return -EINVAL; | ||
1365 | |||
1366 | return v4l2_enum_dv_timings_cap(timings, | ||
1367 | &tc358743_timings_cap, NULL, NULL); | ||
1368 | } | ||
1369 | |||
1370 | static int tc358743_query_dv_timings(struct v4l2_subdev *sd, | ||
1371 | struct v4l2_dv_timings *timings) | ||
1372 | { | ||
1373 | int ret; | ||
1374 | |||
1375 | ret = tc358743_get_detected_timings(sd, timings); | ||
1376 | if (ret) | ||
1377 | return ret; | ||
1378 | |||
1379 | if (debug) | ||
1380 | v4l2_print_dv_timings(sd->name, "tc358743_query_dv_timings: ", | ||
1381 | timings, false); | ||
1382 | |||
1383 | if (!v4l2_valid_dv_timings(timings, | ||
1384 | &tc358743_timings_cap, NULL, NULL)) { | ||
1385 | v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__); | ||
1386 | return -ERANGE; | ||
1387 | } | ||
1388 | |||
1389 | return 0; | ||
1390 | } | ||
1391 | |||
1392 | static int tc358743_dv_timings_cap(struct v4l2_subdev *sd, | ||
1393 | struct v4l2_dv_timings_cap *cap) | ||
1394 | { | ||
1395 | if (cap->pad != 0) | ||
1396 | return -EINVAL; | ||
1397 | |||
1398 | *cap = tc358743_timings_cap; | ||
1399 | |||
1400 | return 0; | ||
1401 | } | ||
1402 | |||
1403 | static int tc358743_g_mbus_config(struct v4l2_subdev *sd, | ||
1404 | struct v4l2_mbus_config *cfg) | ||
1405 | { | ||
1406 | cfg->type = V4L2_MBUS_CSI2; | ||
1407 | |||
1408 | /* Support for non-continuous CSI-2 clock is missing in the driver */ | ||
1409 | cfg->flags = V4L2_MBUS_CSI2_CONTINUOUS_CLOCK; | ||
1410 | |||
1411 | switch (tc358743_num_csi_lanes_in_use(sd)) { | ||
1412 | case 1: | ||
1413 | cfg->flags |= V4L2_MBUS_CSI2_1_LANE; | ||
1414 | break; | ||
1415 | case 2: | ||
1416 | cfg->flags |= V4L2_MBUS_CSI2_2_LANE; | ||
1417 | break; | ||
1418 | case 3: | ||
1419 | cfg->flags |= V4L2_MBUS_CSI2_3_LANE; | ||
1420 | break; | ||
1421 | case 4: | ||
1422 | cfg->flags |= V4L2_MBUS_CSI2_4_LANE; | ||
1423 | break; | ||
1424 | default: | ||
1425 | return -EINVAL; | ||
1426 | } | ||
1427 | |||
1428 | return 0; | ||
1429 | } | ||
1430 | |||
1431 | static int tc358743_s_stream(struct v4l2_subdev *sd, int enable) | ||
1432 | { | ||
1433 | enable_stream(sd, enable); | ||
1434 | |||
1435 | return 0; | ||
1436 | } | ||
1437 | |||
1438 | /* --------------- PAD OPS --------------- */ | ||
1439 | |||
1440 | static int tc358743_get_fmt(struct v4l2_subdev *sd, | ||
1441 | struct v4l2_subdev_pad_config *cfg, | ||
1442 | struct v4l2_subdev_format *format) | ||
1443 | { | ||
1444 | struct tc358743_state *state = to_state(sd); | ||
1445 | u8 vi_rep = i2c_rd8(sd, VI_REP); | ||
1446 | |||
1447 | if (format->pad != 0) | ||
1448 | return -EINVAL; | ||
1449 | |||
1450 | format->format.code = state->mbus_fmt_code; | ||
1451 | format->format.width = state->timings.bt.width; | ||
1452 | format->format.height = state->timings.bt.height; | ||
1453 | format->format.field = V4L2_FIELD_NONE; | ||
1454 | |||
1455 | switch (vi_rep & MASK_VOUT_COLOR_SEL) { | ||
1456 | case MASK_VOUT_COLOR_RGB_FULL: | ||
1457 | case MASK_VOUT_COLOR_RGB_LIMITED: | ||
1458 | format->format.colorspace = V4L2_COLORSPACE_SRGB; | ||
1459 | break; | ||
1460 | case MASK_VOUT_COLOR_601_YCBCR_LIMITED: | ||
1461 | case MASK_VOUT_COLOR_601_YCBCR_FULL: | ||
1462 | format->format.colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
1463 | break; | ||
1464 | case MASK_VOUT_COLOR_709_YCBCR_FULL: | ||
1465 | case MASK_VOUT_COLOR_709_YCBCR_LIMITED: | ||
1466 | format->format.colorspace = V4L2_COLORSPACE_REC709; | ||
1467 | break; | ||
1468 | default: | ||
1469 | format->format.colorspace = 0; | ||
1470 | break; | ||
1471 | } | ||
1472 | |||
1473 | return 0; | ||
1474 | } | ||
1475 | |||
1476 | static int tc358743_set_fmt(struct v4l2_subdev *sd, | ||
1477 | struct v4l2_subdev_pad_config *cfg, | ||
1478 | struct v4l2_subdev_format *format) | ||
1479 | { | ||
1480 | struct tc358743_state *state = to_state(sd); | ||
1481 | |||
1482 | u32 code = format->format.code; /* is overwritten by get_fmt */ | ||
1483 | int ret = tc358743_get_fmt(sd, cfg, format); | ||
1484 | |||
1485 | format->format.code = code; | ||
1486 | |||
1487 | if (ret) | ||
1488 | return ret; | ||
1489 | |||
1490 | switch (code) { | ||
1491 | case MEDIA_BUS_FMT_RGB888_1X24: | ||
1492 | case MEDIA_BUS_FMT_UYVY8_1X16: | ||
1493 | break; | ||
1494 | default: | ||
1495 | return -EINVAL; | ||
1496 | } | ||
1497 | |||
1498 | if (format->which == V4L2_SUBDEV_FORMAT_TRY) | ||
1499 | return 0; | ||
1500 | |||
1501 | state->mbus_fmt_code = format->format.code; | ||
1502 | |||
1503 | enable_stream(sd, false); | ||
1504 | tc358743_set_pll(sd); | ||
1505 | tc358743_set_csi(sd); | ||
1506 | tc358743_set_csi_color_space(sd); | ||
1507 | |||
1508 | return 0; | ||
1509 | } | ||
1510 | |||
1511 | static int tc358743_g_edid(struct v4l2_subdev *sd, | ||
1512 | struct v4l2_subdev_edid *edid) | ||
1513 | { | ||
1514 | struct tc358743_state *state = to_state(sd); | ||
1515 | |||
1516 | if (edid->pad != 0) | ||
1517 | return -EINVAL; | ||
1518 | |||
1519 | if (edid->start_block == 0 && edid->blocks == 0) { | ||
1520 | edid->blocks = state->edid_blocks_written; | ||
1521 | return 0; | ||
1522 | } | ||
1523 | |||
1524 | if (state->edid_blocks_written == 0) | ||
1525 | return -ENODATA; | ||
1526 | |||
1527 | if (edid->start_block >= state->edid_blocks_written || | ||
1528 | edid->blocks == 0) | ||
1529 | return -EINVAL; | ||
1530 | |||
1531 | if (edid->start_block + edid->blocks > state->edid_blocks_written) | ||
1532 | edid->blocks = state->edid_blocks_written - edid->start_block; | ||
1533 | |||
1534 | i2c_rd(sd, EDID_RAM + (edid->start_block * EDID_BLOCK_SIZE), edid->edid, | ||
1535 | edid->blocks * EDID_BLOCK_SIZE); | ||
1536 | |||
1537 | return 0; | ||
1538 | } | ||
1539 | |||
1540 | static int tc358743_s_edid(struct v4l2_subdev *sd, | ||
1541 | struct v4l2_subdev_edid *edid) | ||
1542 | { | ||
1543 | struct tc358743_state *state = to_state(sd); | ||
1544 | u16 edid_len = edid->blocks * EDID_BLOCK_SIZE; | ||
1545 | |||
1546 | v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n", | ||
1547 | __func__, edid->pad, edid->start_block, edid->blocks); | ||
1548 | |||
1549 | if (edid->pad != 0) | ||
1550 | return -EINVAL; | ||
1551 | |||
1552 | if (edid->start_block != 0) | ||
1553 | return -EINVAL; | ||
1554 | |||
1555 | if (edid->blocks > EDID_NUM_BLOCKS_MAX) { | ||
1556 | edid->blocks = EDID_NUM_BLOCKS_MAX; | ||
1557 | return -E2BIG; | ||
1558 | } | ||
1559 | |||
1560 | tc358743_disable_edid(sd); | ||
1561 | |||
1562 | i2c_wr8(sd, EDID_LEN1, edid_len & 0xff); | ||
1563 | i2c_wr8(sd, EDID_LEN2, edid_len >> 8); | ||
1564 | |||
1565 | if (edid->blocks == 0) { | ||
1566 | state->edid_blocks_written = 0; | ||
1567 | return 0; | ||
1568 | } | ||
1569 | |||
1570 | i2c_wr(sd, EDID_RAM, edid->edid, edid_len); | ||
1571 | |||
1572 | state->edid_blocks_written = edid->blocks; | ||
1573 | |||
1574 | if (tx_5v_power_present(sd)) | ||
1575 | tc358743_enable_edid(sd); | ||
1576 | |||
1577 | return 0; | ||
1578 | } | ||
1579 | |||
1580 | /* -------------------------------------------------------------------------- */ | ||
1581 | |||
1582 | static const struct v4l2_subdev_core_ops tc358743_core_ops = { | ||
1583 | .log_status = tc358743_log_status, | ||
1584 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
1585 | .g_register = tc358743_g_register, | ||
1586 | .s_register = tc358743_s_register, | ||
1587 | #endif | ||
1588 | .interrupt_service_routine = tc358743_isr, | ||
1589 | }; | ||
1590 | |||
1591 | static const struct v4l2_subdev_video_ops tc358743_video_ops = { | ||
1592 | .g_input_status = tc358743_g_input_status, | ||
1593 | .s_dv_timings = tc358743_s_dv_timings, | ||
1594 | .g_dv_timings = tc358743_g_dv_timings, | ||
1595 | .query_dv_timings = tc358743_query_dv_timings, | ||
1596 | .g_mbus_config = tc358743_g_mbus_config, | ||
1597 | .s_stream = tc358743_s_stream, | ||
1598 | }; | ||
1599 | |||
1600 | static const struct v4l2_subdev_pad_ops tc358743_pad_ops = { | ||
1601 | .set_fmt = tc358743_set_fmt, | ||
1602 | .get_fmt = tc358743_get_fmt, | ||
1603 | .get_edid = tc358743_g_edid, | ||
1604 | .set_edid = tc358743_s_edid, | ||
1605 | .enum_dv_timings = tc358743_enum_dv_timings, | ||
1606 | .dv_timings_cap = tc358743_dv_timings_cap, | ||
1607 | }; | ||
1608 | |||
1609 | static const struct v4l2_subdev_ops tc358743_ops = { | ||
1610 | .core = &tc358743_core_ops, | ||
1611 | .video = &tc358743_video_ops, | ||
1612 | .pad = &tc358743_pad_ops, | ||
1613 | }; | ||
1614 | |||
1615 | /* --------------- CUSTOM CTRLS --------------- */ | ||
1616 | |||
1617 | static const struct v4l2_ctrl_config tc358743_ctrl_audio_sampling_rate = { | ||
1618 | .id = TC358743_CID_AUDIO_SAMPLING_RATE, | ||
1619 | .name = "Audio sampling rate", | ||
1620 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
1621 | .min = 0, | ||
1622 | .max = 768000, | ||
1623 | .step = 1, | ||
1624 | .def = 0, | ||
1625 | .flags = V4L2_CTRL_FLAG_READ_ONLY, | ||
1626 | }; | ||
1627 | |||
1628 | static const struct v4l2_ctrl_config tc358743_ctrl_audio_present = { | ||
1629 | .id = TC358743_CID_AUDIO_PRESENT, | ||
1630 | .name = "Audio present", | ||
1631 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
1632 | .min = 0, | ||
1633 | .max = 1, | ||
1634 | .step = 1, | ||
1635 | .def = 0, | ||
1636 | .flags = V4L2_CTRL_FLAG_READ_ONLY, | ||
1637 | }; | ||
1638 | |||
1639 | /* --------------- PROBE / REMOVE --------------- */ | ||
1640 | |||
1641 | static int tc358743_probe(struct i2c_client *client, | ||
1642 | const struct i2c_device_id *id) | ||
1643 | { | ||
1644 | static struct v4l2_dv_timings default_timing = | ||
1645 | V4L2_DV_BT_CEA_640X480P59_94; | ||
1646 | struct tc358743_state *state; | ||
1647 | struct tc358743_platform_data *pdata = client->dev.platform_data; | ||
1648 | struct v4l2_subdev *sd; | ||
1649 | int err; | ||
1650 | |||
1651 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
1652 | return -EIO; | ||
1653 | v4l_dbg(1, debug, client, "chip found @ 0x%x (%s)\n", | ||
1654 | client->addr << 1, client->adapter->name); | ||
1655 | |||
1656 | state = devm_kzalloc(&client->dev, sizeof(struct tc358743_state), | ||
1657 | GFP_KERNEL); | ||
1658 | if (!state) | ||
1659 | return -ENOMEM; | ||
1660 | |||
1661 | /* platform data */ | ||
1662 | if (!pdata) { | ||
1663 | v4l_err(client, "No platform data!\n"); | ||
1664 | return -ENODEV; | ||
1665 | } | ||
1666 | state->pdata = *pdata; | ||
1667 | |||
1668 | state->i2c_client = client; | ||
1669 | sd = &state->sd; | ||
1670 | v4l2_i2c_subdev_init(sd, client, &tc358743_ops); | ||
1671 | sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS; | ||
1672 | |||
1673 | /* i2c access */ | ||
1674 | if ((i2c_rd16(sd, CHIPID) & MASK_CHIPID) != 0) { | ||
1675 | v4l2_info(sd, "not a TC358743 on address 0x%x\n", | ||
1676 | client->addr << 1); | ||
1677 | return -ENODEV; | ||
1678 | } | ||
1679 | |||
1680 | /* control handlers */ | ||
1681 | v4l2_ctrl_handler_init(&state->hdl, 3); | ||
1682 | |||
1683 | /* private controls */ | ||
1684 | state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(&state->hdl, NULL, | ||
1685 | V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0); | ||
1686 | |||
1687 | /* custom controls */ | ||
1688 | state->audio_sampling_rate_ctrl = v4l2_ctrl_new_custom(&state->hdl, | ||
1689 | &tc358743_ctrl_audio_sampling_rate, NULL); | ||
1690 | |||
1691 | state->audio_present_ctrl = v4l2_ctrl_new_custom(&state->hdl, | ||
1692 | &tc358743_ctrl_audio_present, NULL); | ||
1693 | |||
1694 | sd->ctrl_handler = &state->hdl; | ||
1695 | if (state->hdl.error) { | ||
1696 | err = state->hdl.error; | ||
1697 | goto err_hdl; | ||
1698 | } | ||
1699 | |||
1700 | if (tc358743_update_controls(sd)) { | ||
1701 | err = -ENODEV; | ||
1702 | goto err_hdl; | ||
1703 | } | ||
1704 | |||
1705 | /* work queues */ | ||
1706 | state->work_queues = create_singlethread_workqueue(client->name); | ||
1707 | if (!state->work_queues) { | ||
1708 | v4l2_err(sd, "Could not create work queue\n"); | ||
1709 | err = -ENOMEM; | ||
1710 | goto err_hdl; | ||
1711 | } | ||
1712 | |||
1713 | mutex_init(&state->confctl_mutex); | ||
1714 | |||
1715 | INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, | ||
1716 | tc358743_delayed_work_enable_hotplug); | ||
1717 | |||
1718 | tc358743_initial_setup(sd); | ||
1719 | |||
1720 | tc358743_s_dv_timings(sd, &default_timing); | ||
1721 | |||
1722 | state->mbus_fmt_code = MEDIA_BUS_FMT_RGB888_1X24; | ||
1723 | tc358743_set_csi_color_space(sd); | ||
1724 | |||
1725 | tc358743_init_interrupts(sd); | ||
1726 | tc358743_enable_interrupts(sd, tx_5v_power_present(sd)); | ||
1727 | i2c_wr16(sd, INTMASK, ~(MASK_HDMI_MSK | MASK_CSI_MSK) & 0xffff); | ||
1728 | |||
1729 | err = v4l2_ctrl_handler_setup(sd->ctrl_handler); | ||
1730 | if (err) | ||
1731 | goto err_work_queues; | ||
1732 | |||
1733 | v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name, | ||
1734 | client->addr << 1, client->adapter->name); | ||
1735 | |||
1736 | return 0; | ||
1737 | |||
1738 | err_work_queues: | ||
1739 | cancel_delayed_work(&state->delayed_work_enable_hotplug); | ||
1740 | destroy_workqueue(state->work_queues); | ||
1741 | mutex_destroy(&state->confctl_mutex); | ||
1742 | err_hdl: | ||
1743 | v4l2_ctrl_handler_free(&state->hdl); | ||
1744 | return err; | ||
1745 | } | ||
1746 | |||
1747 | static int tc358743_remove(struct i2c_client *client) | ||
1748 | { | ||
1749 | struct v4l2_subdev *sd = i2c_get_clientdata(client); | ||
1750 | struct tc358743_state *state = to_state(sd); | ||
1751 | |||
1752 | cancel_delayed_work(&state->delayed_work_enable_hotplug); | ||
1753 | destroy_workqueue(state->work_queues); | ||
1754 | v4l2_device_unregister_subdev(sd); | ||
1755 | mutex_destroy(&state->confctl_mutex); | ||
1756 | v4l2_ctrl_handler_free(&state->hdl); | ||
1757 | |||
1758 | return 0; | ||
1759 | } | ||
1760 | |||
1761 | static struct i2c_device_id tc358743_id[] = { | ||
1762 | {"tc358743", 0}, | ||
1763 | {} | ||
1764 | }; | ||
1765 | |||
1766 | MODULE_DEVICE_TABLE(i2c, tc358743_id); | ||
1767 | |||
1768 | static struct i2c_driver tc358743_driver = { | ||
1769 | .driver = { | ||
1770 | .owner = THIS_MODULE, | ||
1771 | .name = "tc358743", | ||
1772 | }, | ||
1773 | .probe = tc358743_probe, | ||
1774 | .remove = tc358743_remove, | ||
1775 | .id_table = tc358743_id, | ||
1776 | }; | ||
1777 | |||
1778 | module_i2c_driver(tc358743_driver); | ||
diff --git a/drivers/media/i2c/tc358743_regs.h b/drivers/media/i2c/tc358743_regs.h new file mode 100644 index 000000000000..81f1db558e7c --- /dev/null +++ b/drivers/media/i2c/tc358743_regs.h | |||
@@ -0,0 +1,681 @@ | |||
1 | /* | ||
2 | * tc358743 - Toshiba HDMI to CSI-2 bridge - register names and bit masks | ||
3 | * | ||
4 | * Copyright 2015 Cisco Systems, Inc. and/or its affiliates. All rights | ||
5 | * reserved. | ||
6 | * | ||
7 | * This program is free software; you may redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
12 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
13 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
15 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
16 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
17 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
18 | * SOFTWARE. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * References (c = chapter, p = page): | ||
24 | * REF_01 - Toshiba, TC358743XBG (H2C), Functional Specification, Rev 0.60 | ||
25 | */ | ||
26 | |||
27 | /* Bit masks has prefix 'MASK_' and options after '_'. */ | ||
28 | |||
29 | #ifndef __TC358743_REGS_H | ||
30 | #define __TC358743_REGS_H | ||
31 | |||
32 | #define CHIPID 0x0000 | ||
33 | #define MASK_CHIPID 0xff00 | ||
34 | #define MASK_REVID 0x00ff | ||
35 | |||
36 | #define SYSCTL 0x0002 | ||
37 | #define MASK_IRRST 0x0800 | ||
38 | #define MASK_CECRST 0x0400 | ||
39 | #define MASK_CTXRST 0x0200 | ||
40 | #define MASK_HDMIRST 0x0100 | ||
41 | #define MASK_SLEEP 0x0001 | ||
42 | |||
43 | #define CONFCTL 0x0004 | ||
44 | #define MASK_PWRISO 0x8000 | ||
45 | #define MASK_ACLKOPT 0x1000 | ||
46 | #define MASK_AUDCHNUM 0x0c00 | ||
47 | #define MASK_AUDCHNUM_8 0x0000 | ||
48 | #define MASK_AUDCHNUM_6 0x0400 | ||
49 | #define MASK_AUDCHNUM_4 0x0800 | ||
50 | #define MASK_AUDCHNUM_2 0x0c00 | ||
51 | #define MASK_AUDCHSEL 0x0200 | ||
52 | #define MASK_I2SDLYOPT 0x0100 | ||
53 | #define MASK_YCBCRFMT 0x00c0 | ||
54 | #define MASK_YCBCRFMT_444 0x0000 | ||
55 | #define MASK_YCBCRFMT_422_12_BIT 0x0040 | ||
56 | #define MASK_YCBCRFMT_COLORBAR 0x0080 | ||
57 | #define MASK_YCBCRFMT_422_8_BIT 0x00c0 | ||
58 | #define MASK_INFRMEN 0x0020 | ||
59 | #define MASK_AUDOUTSEL 0x0018 | ||
60 | #define MASK_AUDOUTSEL_CSI 0x0000 | ||
61 | #define MASK_AUDOUTSEL_I2S 0x0010 | ||
62 | #define MASK_AUDOUTSEL_TDM 0x0018 | ||
63 | #define MASK_AUTOINDEX 0x0004 | ||
64 | #define MASK_ABUFEN 0x0002 | ||
65 | #define MASK_VBUFEN 0x0001 | ||
66 | |||
67 | #define FIFOCTL 0x0006 | ||
68 | |||
69 | #define INTSTATUS 0x0014 | ||
70 | #define MASK_AMUTE_INT 0x0400 | ||
71 | #define MASK_HDMI_INT 0x0200 | ||
72 | #define MASK_CSI_INT 0x0100 | ||
73 | #define MASK_SYS_INT 0x0020 | ||
74 | #define MASK_CEC_EINT 0x0010 | ||
75 | #define MASK_CEC_TINT 0x0008 | ||
76 | #define MASK_CEC_RINT 0x0004 | ||
77 | #define MASK_IR_EINT 0x0002 | ||
78 | #define MASK_IR_DINT 0x0001 | ||
79 | |||
80 | #define INTMASK 0x0016 | ||
81 | #define MASK_AMUTE_MSK 0x0400 | ||
82 | #define MASK_HDMI_MSK 0x0200 | ||
83 | #define MASK_CSI_MSK 0x0100 | ||
84 | #define MASK_SYS_MSK 0x0020 | ||
85 | #define MASK_CEC_EMSK 0x0010 | ||
86 | #define MASK_CEC_TMSK 0x0008 | ||
87 | #define MASK_CEC_RMSK 0x0004 | ||
88 | #define MASK_IR_EMSK 0x0002 | ||
89 | #define MASK_IR_DMSK 0x0001 | ||
90 | |||
91 | #define INTFLAG 0x0018 | ||
92 | #define INTSYSSTATUS 0x001A | ||
93 | |||
94 | #define PLLCTL0 0x0020 | ||
95 | #define MASK_PLL_PRD 0xf000 | ||
96 | #define SET_PLL_PRD(prd) ((((prd) - 1) << 12) &\ | ||
97 | MASK_PLL_PRD) | ||
98 | #define MASK_PLL_FBD 0x01ff | ||
99 | #define SET_PLL_FBD(fbd) (((fbd) - 1) & MASK_PLL_FBD) | ||
100 | |||
101 | #define PLLCTL1 0x0022 | ||
102 | #define MASK_PLL_FRS 0x0c00 | ||
103 | #define SET_PLL_FRS(frs) (((frs) << 10) & MASK_PLL_FRS) | ||
104 | #define MASK_PLL_LBWS 0x0300 | ||
105 | #define MASK_LFBREN 0x0040 | ||
106 | #define MASK_BYPCKEN 0x0020 | ||
107 | #define MASK_CKEN 0x0010 | ||
108 | #define MASK_RESETB 0x0002 | ||
109 | #define MASK_PLL_EN 0x0001 | ||
110 | |||
111 | #define CLW_CNTRL 0x0140 | ||
112 | #define MASK_CLW_LANEDISABLE 0x0001 | ||
113 | |||
114 | #define D0W_CNTRL 0x0144 | ||
115 | #define MASK_D0W_LANEDISABLE 0x0001 | ||
116 | |||
117 | #define D1W_CNTRL 0x0148 | ||
118 | #define MASK_D1W_LANEDISABLE 0x0001 | ||
119 | |||
120 | #define D2W_CNTRL 0x014C | ||
121 | #define MASK_D2W_LANEDISABLE 0x0001 | ||
122 | |||
123 | #define D3W_CNTRL 0x0150 | ||
124 | #define MASK_D3W_LANEDISABLE 0x0001 | ||
125 | |||
126 | #define STARTCNTRL 0x0204 | ||
127 | #define MASK_START 0x00000001 | ||
128 | |||
129 | #define LINEINITCNT 0x0210 | ||
130 | #define LPTXTIMECNT 0x0214 | ||
131 | #define TCLK_HEADERCNT 0x0218 | ||
132 | #define TCLK_TRAILCNT 0x021C | ||
133 | #define THS_HEADERCNT 0x0220 | ||
134 | #define TWAKEUP 0x0224 | ||
135 | #define TCLK_POSTCNT 0x0228 | ||
136 | #define THS_TRAILCNT 0x022C | ||
137 | #define HSTXVREGCNT 0x0230 | ||
138 | |||
139 | #define HSTXVREGEN 0x0234 | ||
140 | #define MASK_D3M_HSTXVREGEN 0x0010 | ||
141 | #define MASK_D2M_HSTXVREGEN 0x0008 | ||
142 | #define MASK_D1M_HSTXVREGEN 0x0004 | ||
143 | #define MASK_D0M_HSTXVREGEN 0x0002 | ||
144 | #define MASK_CLM_HSTXVREGEN 0x0001 | ||
145 | |||
146 | |||
147 | #define TXOPTIONCNTRL 0x0238 | ||
148 | #define MASK_CONTCLKMODE 0x00000001 | ||
149 | |||
150 | #define CSI_CONTROL 0x040C | ||
151 | #define MASK_CSI_MODE 0x8000 | ||
152 | #define MASK_HTXTOEN 0x0400 | ||
153 | #define MASK_TXHSMD 0x0080 | ||
154 | #define MASK_HSCKMD 0x0020 | ||
155 | #define MASK_NOL 0x0006 | ||
156 | #define MASK_NOL_1 0x0000 | ||
157 | #define MASK_NOL_2 0x0002 | ||
158 | #define MASK_NOL_3 0x0004 | ||
159 | #define MASK_NOL_4 0x0006 | ||
160 | #define MASK_EOTDIS 0x0001 | ||
161 | |||
162 | #define CSI_INT 0x0414 | ||
163 | #define MASK_INTHLT 0x00000008 | ||
164 | #define MASK_INTER 0x00000004 | ||
165 | |||
166 | #define CSI_INT_ENA 0x0418 | ||
167 | #define MASK_IENHLT 0x00000008 | ||
168 | #define MASK_IENER 0x00000004 | ||
169 | |||
170 | #define CSI_ERR 0x044C | ||
171 | #define MASK_INER 0x00000200 | ||
172 | #define MASK_WCER 0x00000100 | ||
173 | #define MASK_QUNK 0x00000010 | ||
174 | #define MASK_TXBRK 0x00000002 | ||
175 | |||
176 | #define CSI_ERR_INTENA 0x0450 | ||
177 | #define CSI_ERR_HALT 0x0454 | ||
178 | |||
179 | #define CSI_CONFW 0x0500 | ||
180 | #define MASK_MODE 0xe0000000 | ||
181 | #define MASK_MODE_SET 0xa0000000 | ||
182 | #define MASK_MODE_CLEAR 0xc0000000 | ||
183 | #define MASK_ADDRESS 0x1f000000 | ||
184 | #define MASK_ADDRESS_CSI_CONTROL 0x03000000 | ||
185 | #define MASK_ADDRESS_CSI_INT_ENA 0x06000000 | ||
186 | #define MASK_ADDRESS_CSI_ERR_INTENA 0x14000000 | ||
187 | #define MASK_ADDRESS_CSI_ERR_HALT 0x15000000 | ||
188 | #define MASK_DATA 0x0000ffff | ||
189 | |||
190 | #define CSI_INT_CLR 0x050C | ||
191 | #define MASK_ICRER 0x00000004 | ||
192 | |||
193 | #define CSI_START 0x0518 | ||
194 | #define MASK_STRT 0x00000001 | ||
195 | |||
196 | #define CECEN 0x0600 | ||
197 | #define MASK_CECEN 0x0001 | ||
198 | |||
199 | #define HDMI_INT0 0x8500 | ||
200 | #define MASK_I_KEY 0x80 | ||
201 | #define MASK_I_MISC 0x02 | ||
202 | #define MASK_I_PHYERR 0x01 | ||
203 | |||
204 | #define HDMI_INT1 0x8501 | ||
205 | #define MASK_I_GBD 0x80 | ||
206 | #define MASK_I_HDCP 0x40 | ||
207 | #define MASK_I_ERR 0x20 | ||
208 | #define MASK_I_AUD 0x10 | ||
209 | #define MASK_I_CBIT 0x08 | ||
210 | #define MASK_I_PACKET 0x04 | ||
211 | #define MASK_I_CLK 0x02 | ||
212 | #define MASK_I_SYS 0x01 | ||
213 | |||
214 | #define SYS_INT 0x8502 | ||
215 | #define MASK_I_ACR_CTS 0x80 | ||
216 | #define MASK_I_ACRN 0x40 | ||
217 | #define MASK_I_DVI 0x20 | ||
218 | #define MASK_I_HDMI 0x10 | ||
219 | #define MASK_I_NOPMBDET 0x08 | ||
220 | #define MASK_I_DPMBDET 0x04 | ||
221 | #define MASK_I_TMDS 0x02 | ||
222 | #define MASK_I_DDC 0x01 | ||
223 | |||
224 | #define CLK_INT 0x8503 | ||
225 | #define MASK_I_OUT_H_CHG 0x40 | ||
226 | #define MASK_I_IN_DE_CHG 0x20 | ||
227 | #define MASK_I_IN_HV_CHG 0x10 | ||
228 | #define MASK_I_DC_CHG 0x08 | ||
229 | #define MASK_I_PXCLK_CHG 0x04 | ||
230 | #define MASK_I_PHYCLK_CHG 0x02 | ||
231 | #define MASK_I_TMDSCLK_CHG 0x01 | ||
232 | |||
233 | #define CBIT_INT 0x8505 | ||
234 | #define MASK_I_AF_LOCK 0x80 | ||
235 | #define MASK_I_AF_UNLOCK 0x40 | ||
236 | #define MASK_I_CBIT_FS 0x02 | ||
237 | |||
238 | #define AUDIO_INT 0x8506 | ||
239 | |||
240 | #define ERR_INT 0x8507 | ||
241 | #define MASK_I_EESS_ERR 0x80 | ||
242 | |||
243 | #define HDCP_INT 0x8508 | ||
244 | #define MASK_I_AVM_SET 0x80 | ||
245 | #define MASK_I_AVM_CLR 0x40 | ||
246 | #define MASK_I_LINKERR 0x20 | ||
247 | #define MASK_I_SHA_END 0x10 | ||
248 | #define MASK_I_R0_END 0x08 | ||
249 | #define MASK_I_KM_END 0x04 | ||
250 | #define MASK_I_AKSV_END 0x02 | ||
251 | #define MASK_I_AN_END 0x01 | ||
252 | |||
253 | #define MISC_INT 0x850B | ||
254 | #define MASK_I_AS_LAYOUT 0x10 | ||
255 | #define MASK_I_NO_SPD 0x08 | ||
256 | #define MASK_I_NO_VS 0x03 | ||
257 | #define MASK_I_SYNC_CHG 0x02 | ||
258 | #define MASK_I_AUDIO_MUTE 0x01 | ||
259 | |||
260 | #define KEY_INT 0x850F | ||
261 | |||
262 | #define SYS_INTM 0x8512 | ||
263 | #define MASK_M_ACR_CTS 0x80 | ||
264 | #define MASK_M_ACR_N 0x40 | ||
265 | #define MASK_M_DVI_DET 0x20 | ||
266 | #define MASK_M_HDMI_DET 0x10 | ||
267 | #define MASK_M_NOPMBDET 0x08 | ||
268 | #define MASK_M_BPMBDET 0x04 | ||
269 | #define MASK_M_TMDS 0x02 | ||
270 | #define MASK_M_DDC 0x01 | ||
271 | |||
272 | #define CLK_INTM 0x8513 | ||
273 | #define MASK_M_OUT_H_CHG 0x40 | ||
274 | #define MASK_M_IN_DE_CHG 0x20 | ||
275 | #define MASK_M_IN_HV_CHG 0x10 | ||
276 | #define MASK_M_DC_CHG 0x08 | ||
277 | #define MASK_M_PXCLK_CHG 0x04 | ||
278 | #define MASK_M_PHYCLK_CHG 0x02 | ||
279 | #define MASK_M_TMDS_CHG 0x01 | ||
280 | |||
281 | #define PACKET_INTM 0x8514 | ||
282 | |||
283 | #define CBIT_INTM 0x8515 | ||
284 | #define MASK_M_AF_LOCK 0x80 | ||
285 | #define MASK_M_AF_UNLOCK 0x40 | ||
286 | #define MASK_M_CBIT_FS 0x02 | ||
287 | |||
288 | #define AUDIO_INTM 0x8516 | ||
289 | #define MASK_M_BUFINIT_END 0x01 | ||
290 | |||
291 | #define ERR_INTM 0x8517 | ||
292 | #define MASK_M_EESS_ERR 0x80 | ||
293 | |||
294 | #define HDCP_INTM 0x8518 | ||
295 | #define MASK_M_AVM_SET 0x80 | ||
296 | #define MASK_M_AVM_CLR 0x40 | ||
297 | #define MASK_M_LINKERR 0x20 | ||
298 | #define MASK_M_SHA_END 0x10 | ||
299 | #define MASK_M_R0_END 0x08 | ||
300 | #define MASK_M_KM_END 0x04 | ||
301 | #define MASK_M_AKSV_END 0x02 | ||
302 | #define MASK_M_AN_END 0x01 | ||
303 | |||
304 | #define MISC_INTM 0x851B | ||
305 | #define MASK_M_AS_LAYOUT 0x10 | ||
306 | #define MASK_M_NO_SPD 0x08 | ||
307 | #define MASK_M_NO_VS 0x03 | ||
308 | #define MASK_M_SYNC_CHG 0x02 | ||
309 | #define MASK_M_AUDIO_MUTE 0x01 | ||
310 | |||
311 | #define KEY_INTM 0x851F | ||
312 | |||
313 | #define SYS_STATUS 0x8520 | ||
314 | #define MASK_S_SYNC 0x80 | ||
315 | #define MASK_S_AVMUTE 0x40 | ||
316 | #define MASK_S_HDCP 0x20 | ||
317 | #define MASK_S_HDMI 0x10 | ||
318 | #define MASK_S_PHY_SCDT 0x08 | ||
319 | #define MASK_S_PHY_PLL 0x04 | ||
320 | #define MASK_S_TMDS 0x02 | ||
321 | #define MASK_S_DDC5V 0x01 | ||
322 | |||
323 | #define CSI_STATUS 0x0410 | ||
324 | #define MASK_S_WSYNC 0x0400 | ||
325 | #define MASK_S_TXACT 0x0200 | ||
326 | #define MASK_S_RXACT 0x0100 | ||
327 | #define MASK_S_HLT 0x0001 | ||
328 | |||
329 | #define VI_STATUS1 0x8522 | ||
330 | #define MASK_S_V_GBD 0x08 | ||
331 | #define MASK_S_DEEPCOLOR 0x0c | ||
332 | #define MASK_S_V_422 0x02 | ||
333 | #define MASK_S_V_INTERLACE 0x01 | ||
334 | |||
335 | #define AU_STATUS0 0x8523 | ||
336 | #define MASK_S_A_SAMPLE 0x01 | ||
337 | |||
338 | #define VI_STATUS3 0x8528 | ||
339 | #define MASK_S_V_COLOR 0x1e | ||
340 | #define MASK_LIMITED 0x01 | ||
341 | |||
342 | #define PHY_CTL0 0x8531 | ||
343 | #define MASK_PHY_SYSCLK_IND 0x02 | ||
344 | #define MASK_PHY_CTL 0x01 | ||
345 | |||
346 | |||
347 | #define PHY_CTL1 0x8532 /* Not in REF_01 */ | ||
348 | #define MASK_PHY_AUTO_RST1 0xf0 | ||
349 | #define MASK_PHY_AUTO_RST1_OFF 0x00 | ||
350 | #define SET_PHY_AUTO_RST1_US(us) ((((us) / 200) << 4) & \ | ||
351 | MASK_PHY_AUTO_RST1) | ||
352 | #define MASK_FREQ_RANGE_MODE 0x0f | ||
353 | #define SET_FREQ_RANGE_MODE_CYCLES(cycles) (((cycles) - 1) & \ | ||
354 | MASK_FREQ_RANGE_MODE) | ||
355 | |||
356 | #define PHY_CTL2 0x8533 /* Not in REF_01 */ | ||
357 | #define MASK_PHY_AUTO_RST4 0x04 | ||
358 | #define MASK_PHY_AUTO_RST3 0x02 | ||
359 | #define MASK_PHY_AUTO_RST2 0x01 | ||
360 | #define MASK_PHY_AUTO_RSTn (MASK_PHY_AUTO_RST4 | \ | ||
361 | MASK_PHY_AUTO_RST3 | \ | ||
362 | MASK_PHY_AUTO_RST2) | ||
363 | |||
364 | #define PHY_EN 0x8534 | ||
365 | #define MASK_ENABLE_PHY 0x01 | ||
366 | |||
367 | #define PHY_RST 0x8535 | ||
368 | #define MASK_RESET_CTRL 0x01 /* Reset active low */ | ||
369 | |||
370 | #define PHY_BIAS 0x8536 /* Not in REF_01 */ | ||
371 | |||
372 | #define PHY_CSQ 0x853F /* Not in REF_01 */ | ||
373 | #define MASK_CSQ_CNT 0x0f | ||
374 | #define SET_CSQ_CNT_LEVEL(n) (n & MASK_CSQ_CNT) | ||
375 | |||
376 | #define SYS_FREQ0 0x8540 | ||
377 | #define SYS_FREQ1 0x8541 | ||
378 | |||
379 | #define SYS_CLK 0x8542 /* Not in REF_01 */ | ||
380 | #define MASK_CLK_DIFF 0x0C | ||
381 | #define MASK_CLK_DIV 0x03 | ||
382 | |||
383 | #define DDC_CTL 0x8543 | ||
384 | #define MASK_DDC_ACK_POL 0x08 | ||
385 | #define MASK_DDC_ACTION 0x04 | ||
386 | #define MASK_DDC5V_MODE 0x03 | ||
387 | #define MASK_DDC5V_MODE_0MS 0x00 | ||
388 | #define MASK_DDC5V_MODE_50MS 0x01 | ||
389 | #define MASK_DDC5V_MODE_100MS 0x02 | ||
390 | #define MASK_DDC5V_MODE_200MS 0x03 | ||
391 | |||
392 | #define HPD_CTL 0x8544 | ||
393 | #define MASK_HPD_CTL0 0x10 | ||
394 | #define MASK_HPD_OUT0 0x01 | ||
395 | |||
396 | #define ANA_CTL 0x8545 | ||
397 | #define MASK_APPL_PCSX 0x30 | ||
398 | #define MASK_APPL_PCSX_HIZ 0x00 | ||
399 | #define MASK_APPL_PCSX_L_FIX 0x10 | ||
400 | #define MASK_APPL_PCSX_H_FIX 0x20 | ||
401 | #define MASK_APPL_PCSX_NORMAL 0x30 | ||
402 | #define MASK_ANALOG_ON 0x01 | ||
403 | |||
404 | #define AVM_CTL 0x8546 | ||
405 | |||
406 | #define INIT_END 0x854A | ||
407 | #define MASK_INIT_END 0x01 | ||
408 | |||
409 | #define HDMI_DET 0x8552 /* Not in REF_01 */ | ||
410 | #define MASK_HDMI_DET_MOD1 0x80 | ||
411 | #define MASK_HDMI_DET_MOD0 0x40 | ||
412 | #define MASK_HDMI_DET_V 0x30 | ||
413 | #define MASK_HDMI_DET_V_SYNC 0x00 | ||
414 | #define MASK_HDMI_DET_V_ASYNC_25MS 0x10 | ||
415 | #define MASK_HDMI_DET_V_ASYNC_50MS 0x20 | ||
416 | #define MASK_HDMI_DET_V_ASYNC_100MS 0x30 | ||
417 | #define MASK_HDMI_DET_NUM 0x0f | ||
418 | |||
419 | #define HDCP_MODE 0x8560 | ||
420 | #define MASK_MODE_RST_TN 0x20 | ||
421 | #define MASK_LINE_REKEY 0x10 | ||
422 | #define MASK_AUTO_CLR 0x04 | ||
423 | |||
424 | #define HDCP_REG1 0x8563 /* Not in REF_01 */ | ||
425 | #define MASK_AUTH_UNAUTH_SEL 0x70 | ||
426 | #define MASK_AUTH_UNAUTH_SEL_12_FRAMES 0x70 | ||
427 | #define MASK_AUTH_UNAUTH_SEL_8_FRAMES 0x60 | ||
428 | #define MASK_AUTH_UNAUTH_SEL_4_FRAMES 0x50 | ||
429 | #define MASK_AUTH_UNAUTH_SEL_2_FRAMES 0x40 | ||
430 | #define MASK_AUTH_UNAUTH_SEL_64_FRAMES 0x30 | ||
431 | #define MASK_AUTH_UNAUTH_SEL_32_FRAMES 0x20 | ||
432 | #define MASK_AUTH_UNAUTH_SEL_16_FRAMES 0x10 | ||
433 | #define MASK_AUTH_UNAUTH_SEL_ONCE 0x00 | ||
434 | #define MASK_AUTH_UNAUTH 0x01 | ||
435 | #define MASK_AUTH_UNAUTH_AUTO 0x01 | ||
436 | |||
437 | #define HDCP_REG2 0x8564 /* Not in REF_01 */ | ||
438 | #define MASK_AUTO_P3_RESET 0x0F | ||
439 | #define SET_AUTO_P3_RESET_FRAMES(n) (n & MASK_AUTO_P3_RESET) | ||
440 | #define MASK_AUTO_P3_RESET_OFF 0x00 | ||
441 | |||
442 | #define VI_MODE 0x8570 | ||
443 | #define MASK_RGB_DVI 0x08 /* Not in REF_01 */ | ||
444 | |||
445 | #define VOUT_SET2 0x8573 | ||
446 | #define MASK_SEL422 0x80 | ||
447 | #define MASK_VOUT_422FIL_100 0x40 | ||
448 | #define MASK_VOUTCOLORMODE 0x03 | ||
449 | #define MASK_VOUTCOLORMODE_THROUGH 0x00 | ||
450 | #define MASK_VOUTCOLORMODE_AUTO 0x01 | ||
451 | #define MASK_VOUTCOLORMODE_MANUAL 0x03 | ||
452 | |||
453 | #define VOUT_SET3 0x8574 | ||
454 | #define MASK_VOUT_EXTCNT 0x08 | ||
455 | |||
456 | #define VI_REP 0x8576 | ||
457 | #define MASK_VOUT_COLOR_SEL 0xe0 | ||
458 | #define MASK_VOUT_COLOR_RGB_FULL 0x00 | ||
459 | #define MASK_VOUT_COLOR_RGB_LIMITED 0x20 | ||
460 | #define MASK_VOUT_COLOR_601_YCBCR_FULL 0x40 | ||
461 | #define MASK_VOUT_COLOR_601_YCBCR_LIMITED 0x60 | ||
462 | #define MASK_VOUT_COLOR_709_YCBCR_FULL 0x80 | ||
463 | #define MASK_VOUT_COLOR_709_YCBCR_LIMITED 0xa0 | ||
464 | #define MASK_VOUT_COLOR_FULL_TO_LIMITED 0xc0 | ||
465 | #define MASK_VOUT_COLOR_LIMITED_TO_FULL 0xe0 | ||
466 | #define MASK_IN_REP_HEN 0x10 | ||
467 | #define MASK_IN_REP 0x0f | ||
468 | |||
469 | #define VI_MUTE 0x857F | ||
470 | #define MASK_AUTO_MUTE 0xc0 | ||
471 | #define MASK_VI_MUTE 0x10 | ||
472 | |||
473 | #define DE_WIDTH_H_LO 0x8582 /* Not in REF_01 */ | ||
474 | #define DE_WIDTH_H_HI 0x8583 /* Not in REF_01 */ | ||
475 | #define DE_WIDTH_V_LO 0x8588 /* Not in REF_01 */ | ||
476 | #define DE_WIDTH_V_HI 0x8589 /* Not in REF_01 */ | ||
477 | #define H_SIZE_LO 0x858A /* Not in REF_01 */ | ||
478 | #define H_SIZE_HI 0x858B /* Not in REF_01 */ | ||
479 | #define V_SIZE_LO 0x858C /* Not in REF_01 */ | ||
480 | #define V_SIZE_HI 0x858D /* Not in REF_01 */ | ||
481 | #define FV_CNT_LO 0x85A1 /* Not in REF_01 */ | ||
482 | #define FV_CNT_HI 0x85A2 /* Not in REF_01 */ | ||
483 | |||
484 | #define FH_MIN0 0x85AA /* Not in REF_01 */ | ||
485 | #define FH_MIN1 0x85AB /* Not in REF_01 */ | ||
486 | #define FH_MAX0 0x85AC /* Not in REF_01 */ | ||
487 | #define FH_MAX1 0x85AD /* Not in REF_01 */ | ||
488 | |||
489 | #define HV_RST 0x85AF /* Not in REF_01 */ | ||
490 | #define MASK_H_PI_RST 0x20 | ||
491 | #define MASK_V_PI_RST 0x10 | ||
492 | |||
493 | #define EDID_MODE 0x85C7 | ||
494 | #define MASK_EDID_SPEED 0x40 | ||
495 | #define MASK_EDID_MODE 0x03 | ||
496 | #define MASK_EDID_MODE_DISABLE 0x00 | ||
497 | #define MASK_EDID_MODE_DDC2B 0x01 | ||
498 | #define MASK_EDID_MODE_E_DDC 0x02 | ||
499 | |||
500 | #define EDID_LEN1 0x85CA | ||
501 | #define EDID_LEN2 0x85CB | ||
502 | |||
503 | #define HDCP_REG3 0x85D1 /* Not in REF_01 */ | ||
504 | #define KEY_RD_CMD 0x01 | ||
505 | |||
506 | #define FORCE_MUTE 0x8600 | ||
507 | #define MASK_FORCE_AMUTE 0x10 | ||
508 | #define MASK_FORCE_DMUTE 0x01 | ||
509 | |||
510 | #define CMD_AUD 0x8601 | ||
511 | #define MASK_CMD_BUFINIT 0x04 | ||
512 | #define MASK_CMD_LOCKDET 0x02 | ||
513 | #define MASK_CMD_MUTE 0x01 | ||
514 | |||
515 | #define AUTO_CMD0 0x8602 | ||
516 | #define MASK_AUTO_MUTE7 0x80 | ||
517 | #define MASK_AUTO_MUTE6 0x40 | ||
518 | #define MASK_AUTO_MUTE5 0x20 | ||
519 | #define MASK_AUTO_MUTE4 0x10 | ||
520 | #define MASK_AUTO_MUTE3 0x08 | ||
521 | #define MASK_AUTO_MUTE2 0x04 | ||
522 | #define MASK_AUTO_MUTE1 0x02 | ||
523 | #define MASK_AUTO_MUTE0 0x01 | ||
524 | |||
525 | #define AUTO_CMD1 0x8603 | ||
526 | #define MASK_AUTO_MUTE10 0x04 | ||
527 | #define MASK_AUTO_MUTE9 0x02 | ||
528 | #define MASK_AUTO_MUTE8 0x01 | ||
529 | |||
530 | #define AUTO_CMD2 0x8604 | ||
531 | #define MASK_AUTO_PLAY3 0x08 | ||
532 | #define MASK_AUTO_PLAY2 0x04 | ||
533 | |||
534 | #define BUFINIT_START 0x8606 | ||
535 | #define SET_BUFINIT_START_MS(milliseconds) ((milliseconds) / 100) | ||
536 | |||
537 | #define FS_MUTE 0x8607 | ||
538 | #define MASK_FS_ELSE_MUTE 0x80 | ||
539 | #define MASK_FS22_MUTE 0x40 | ||
540 | #define MASK_FS24_MUTE 0x20 | ||
541 | #define MASK_FS88_MUTE 0x10 | ||
542 | #define MASK_FS96_MUTE 0x08 | ||
543 | #define MASK_FS176_MUTE 0x04 | ||
544 | #define MASK_FS192_MUTE 0x02 | ||
545 | #define MASK_FS_NO_MUTE 0x01 | ||
546 | |||
547 | #define FS_IMODE 0x8620 | ||
548 | #define MASK_NLPCM_HMODE 0x40 | ||
549 | #define MASK_NLPCM_SMODE 0x20 | ||
550 | #define MASK_NLPCM_IMODE 0x10 | ||
551 | #define MASK_FS_HMODE 0x08 | ||
552 | #define MASK_FS_AMODE 0x04 | ||
553 | #define MASK_FS_SMODE 0x02 | ||
554 | #define MASK_FS_IMODE 0x01 | ||
555 | |||
556 | #define FS_SET 0x8621 | ||
557 | #define MASK_FS 0x0f | ||
558 | |||
559 | #define LOCKDET_REF0 0x8630 | ||
560 | #define LOCKDET_REF1 0x8631 | ||
561 | #define LOCKDET_REF2 0x8632 | ||
562 | |||
563 | #define ACR_MODE 0x8640 | ||
564 | #define MASK_ACR_LOAD 0x10 | ||
565 | #define MASK_N_MODE 0x04 | ||
566 | #define MASK_CTS_MODE 0x01 | ||
567 | |||
568 | #define ACR_MDF0 0x8641 | ||
569 | #define MASK_ACR_L2MDF 0x70 | ||
570 | #define MASK_ACR_L2MDF_0_PPM 0x00 | ||
571 | #define MASK_ACR_L2MDF_61_PPM 0x10 | ||
572 | #define MASK_ACR_L2MDF_122_PPM 0x20 | ||
573 | #define MASK_ACR_L2MDF_244_PPM 0x30 | ||
574 | #define MASK_ACR_L2MDF_488_PPM 0x40 | ||
575 | #define MASK_ACR_L2MDF_976_PPM 0x50 | ||
576 | #define MASK_ACR_L2MDF_1976_PPM 0x60 | ||
577 | #define MASK_ACR_L2MDF_3906_PPM 0x70 | ||
578 | #define MASK_ACR_L1MDF 0x07 | ||
579 | #define MASK_ACR_L1MDF_0_PPM 0x00 | ||
580 | #define MASK_ACR_L1MDF_61_PPM 0x01 | ||
581 | #define MASK_ACR_L1MDF_122_PPM 0x02 | ||
582 | #define MASK_ACR_L1MDF_244_PPM 0x03 | ||
583 | #define MASK_ACR_L1MDF_488_PPM 0x04 | ||
584 | #define MASK_ACR_L1MDF_976_PPM 0x05 | ||
585 | #define MASK_ACR_L1MDF_1976_PPM 0x06 | ||
586 | #define MASK_ACR_L1MDF_3906_PPM 0x07 | ||
587 | |||
588 | #define ACR_MDF1 0x8642 | ||
589 | #define MASK_ACR_L3MDF 0x07 | ||
590 | #define MASK_ACR_L3MDF_0_PPM 0x00 | ||
591 | #define MASK_ACR_L3MDF_61_PPM 0x01 | ||
592 | #define MASK_ACR_L3MDF_122_PPM 0x02 | ||
593 | #define MASK_ACR_L3MDF_244_PPM 0x03 | ||
594 | #define MASK_ACR_L3MDF_488_PPM 0x04 | ||
595 | #define MASK_ACR_L3MDF_976_PPM 0x05 | ||
596 | #define MASK_ACR_L3MDF_1976_PPM 0x06 | ||
597 | #define MASK_ACR_L3MDF_3906_PPM 0x07 | ||
598 | |||
599 | #define SDO_MODE1 0x8652 | ||
600 | #define MASK_SDO_BIT_LENG 0x70 | ||
601 | #define MASK_SDO_FMT 0x03 | ||
602 | #define MASK_SDO_FMT_RIGHT 0x00 | ||
603 | #define MASK_SDO_FMT_LEFT 0x01 | ||
604 | #define MASK_SDO_FMT_I2S 0x02 | ||
605 | |||
606 | #define DIV_MODE 0x8665 /* Not in REF_01 */ | ||
607 | #define MASK_DIV_DLY 0xf0 | ||
608 | #define SET_DIV_DLY_MS(milliseconds) ((((milliseconds) / 100) << 4) & \ | ||
609 | MASK_DIV_DLY) | ||
610 | #define MASK_DIV_MODE 0x01 | ||
611 | |||
612 | #define NCO_F0_MOD 0x8670 | ||
613 | #define MASK_NCO_F0_MOD 0x03 | ||
614 | #define MASK_NCO_F0_MOD_42MHZ 0x00 | ||
615 | #define MASK_NCO_F0_MOD_27MHZ 0x01 | ||
616 | |||
617 | #define PK_INT_MODE 0x8709 | ||
618 | #define MASK_ISRC2_INT_MODE 0x80 | ||
619 | #define MASK_ISRC_INT_MODE 0x40 | ||
620 | #define MASK_ACP_INT_MODE 0x20 | ||
621 | #define MASK_VS_INT_MODE 0x10 | ||
622 | #define MASK_SPD_INT_MODE 0x08 | ||
623 | #define MASK_MS_INT_MODE 0x04 | ||
624 | #define MASK_AUD_INT_MODE 0x02 | ||
625 | #define MASK_AVI_INT_MODE 0x01 | ||
626 | |||
627 | #define NO_PKT_LIMIT 0x870B | ||
628 | #define MASK_NO_ACP_LIMIT 0xf0 | ||
629 | #define SET_NO_ACP_LIMIT_MS(milliseconds) ((((milliseconds) / 80) << 4) & \ | ||
630 | MASK_NO_ACP_LIMIT) | ||
631 | #define MASK_NO_AVI_LIMIT 0x0f | ||
632 | #define SET_NO_AVI_LIMIT_MS(milliseconds) (((milliseconds) / 80) & \ | ||
633 | MASK_NO_AVI_LIMIT) | ||
634 | |||
635 | #define NO_PKT_CLR 0x870C | ||
636 | #define MASK_NO_VS_CLR 0x40 | ||
637 | #define MASK_NO_SPD_CLR 0x20 | ||
638 | #define MASK_NO_ACP_CLR 0x10 | ||
639 | #define MASK_NO_AVI_CLR1 0x02 | ||
640 | #define MASK_NO_AVI_CLR0 0x01 | ||
641 | |||
642 | #define ERR_PK_LIMIT 0x870D | ||
643 | #define NO_PKT_LIMIT2 0x870E | ||
644 | #define PK_AVI_0HEAD 0x8710 | ||
645 | #define PK_AVI_1HEAD 0x8711 | ||
646 | #define PK_AVI_2HEAD 0x8712 | ||
647 | #define PK_AVI_0BYTE 0x8713 | ||
648 | #define PK_AVI_1BYTE 0x8714 | ||
649 | #define PK_AVI_2BYTE 0x8715 | ||
650 | #define PK_AVI_3BYTE 0x8716 | ||
651 | #define PK_AVI_4BYTE 0x8717 | ||
652 | #define PK_AVI_5BYTE 0x8718 | ||
653 | #define PK_AVI_6BYTE 0x8719 | ||
654 | #define PK_AVI_7BYTE 0x871A | ||
655 | #define PK_AVI_8BYTE 0x871B | ||
656 | #define PK_AVI_9BYTE 0x871C | ||
657 | #define PK_AVI_10BYTE 0x871D | ||
658 | #define PK_AVI_11BYTE 0x871E | ||
659 | #define PK_AVI_12BYTE 0x871F | ||
660 | #define PK_AVI_13BYTE 0x8720 | ||
661 | #define PK_AVI_14BYTE 0x8721 | ||
662 | #define PK_AVI_15BYTE 0x8722 | ||
663 | #define PK_AVI_16BYTE 0x8723 | ||
664 | |||
665 | #define BKSV 0x8800 | ||
666 | |||
667 | #define BCAPS 0x8840 | ||
668 | #define MASK_HDMI_RSVD 0x80 | ||
669 | #define MASK_REPEATER 0x40 | ||
670 | #define MASK_READY 0x20 | ||
671 | #define MASK_FASTI2C 0x10 | ||
672 | #define MASK_1_1_FEA 0x02 | ||
673 | #define MASK_FAST_REAU 0x01 | ||
674 | |||
675 | #define BSTATUS1 0x8842 | ||
676 | #define MASK_MAX_EXCED 0x08 | ||
677 | |||
678 | #define EDID_RAM 0x8C00 | ||
679 | #define NO_GDB_LIMIT 0x9007 | ||
680 | |||
681 | #endif | ||
diff --git a/include/media/tc358743.h b/include/media/tc358743.h new file mode 100644 index 000000000000..4513f2f9cfbc --- /dev/null +++ b/include/media/tc358743.h | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * tc358743 - Toshiba HDMI to CSI-2 bridge | ||
3 | * | ||
4 | * Copyright 2015 Cisco Systems, Inc. and/or its affiliates. All rights | ||
5 | * reserved. | ||
6 | * | ||
7 | * This program is free software; you may redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
12 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
13 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | ||
15 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | ||
16 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
17 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
18 | * SOFTWARE. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * References (c = chapter, p = page): | ||
24 | * REF_01 - Toshiba, TC358743XBG (H2C), Functional Specification, Rev 0.60 | ||
25 | * REF_02 - Toshiba, TC358743XBG_HDMI-CSI_Tv11p_nm.xls | ||
26 | */ | ||
27 | |||
28 | #ifndef _TC358743_ | ||
29 | #define _TC358743_ | ||
30 | |||
31 | enum tc358743_ddc5v_delays { | ||
32 | DDC5V_DELAY_0_MS, | ||
33 | DDC5V_DELAY_50_MS, | ||
34 | DDC5V_DELAY_100_MS, | ||
35 | DDC5V_DELAY_200_MS, | ||
36 | }; | ||
37 | |||
38 | enum tc358743_hdmi_detection_delay { | ||
39 | HDMI_MODE_DELAY_0_MS, | ||
40 | HDMI_MODE_DELAY_25_MS, | ||
41 | HDMI_MODE_DELAY_50_MS, | ||
42 | HDMI_MODE_DELAY_100_MS, | ||
43 | }; | ||
44 | |||
45 | struct tc358743_platform_data { | ||
46 | /* System clock connected to REFCLK (pin H5) */ | ||
47 | u32 refclk_hz; /* 26 MHz, 27 MHz or 42 MHz */ | ||
48 | |||
49 | /* DDC +5V debounce delay to avoid spurious interrupts when the cable | ||
50 | * is connected. | ||
51 | * Sets DDC5V_MODE in register DDC_CTL. | ||
52 | * Default: DDC5V_DELAY_0_MS | ||
53 | */ | ||
54 | enum tc358743_ddc5v_delays ddc5v_delay; | ||
55 | |||
56 | bool enable_hdcp; | ||
57 | |||
58 | /* | ||
59 | * The FIFO size is 512x32, so Toshiba recommend to set the default FIFO | ||
60 | * level to somewhere in the middle (e.g. 300), so it can cover speed | ||
61 | * mismatches in input and output ports. | ||
62 | */ | ||
63 | u16 fifo_level; | ||
64 | |||
65 | /* Bps pr lane is (refclk_hz / pll_prd) * pll_fbd */ | ||
66 | u16 pll_prd; | ||
67 | u16 pll_fbd; | ||
68 | |||
69 | /* CSI | ||
70 | * Calculate CSI parameters with REF_02 for the highest resolution your | ||
71 | * CSI interface can handle. The driver will adjust the number of CSI | ||
72 | * lanes in use according to the pixel clock. | ||
73 | * | ||
74 | * The values in brackets are calculated with REF_02 when the number of | ||
75 | * bps pr lane is 823.5 MHz, and can serve as a starting point. | ||
76 | */ | ||
77 | u32 lineinitcnt; /* (0x00001770) */ | ||
78 | u32 lptxtimecnt; /* (0x00000005) */ | ||
79 | u32 tclk_headercnt; /* (0x00001d04) */ | ||
80 | u32 tclk_trailcnt; /* (0x00000000) */ | ||
81 | u32 ths_headercnt; /* (0x00000505) */ | ||
82 | u32 twakeup; /* (0x00004650) */ | ||
83 | u32 tclk_postcnt; /* (0x00000000) */ | ||
84 | u32 ths_trailcnt; /* (0x00000004) */ | ||
85 | u32 hstxvregcnt; /* (0x00000005) */ | ||
86 | |||
87 | /* DVI->HDMI detection delay to avoid unnecessary switching between DVI | ||
88 | * and HDMI mode. | ||
89 | * Sets HDMI_DET_V in register HDMI_DET. | ||
90 | * Default: HDMI_MODE_DELAY_0_MS | ||
91 | */ | ||
92 | enum tc358743_hdmi_detection_delay hdmi_detection_delay; | ||
93 | |||
94 | /* Reset PHY automatically when TMDS clock goes from DC to AC. | ||
95 | * Sets PHY_AUTO_RST2 in register PHY_CTL2. | ||
96 | * Default: false | ||
97 | */ | ||
98 | bool hdmi_phy_auto_reset_tmds_detected; | ||
99 | |||
100 | /* Reset PHY automatically when TMDS clock passes 21 MHz. | ||
101 | * Sets PHY_AUTO_RST3 in register PHY_CTL2. | ||
102 | * Default: false | ||
103 | */ | ||
104 | bool hdmi_phy_auto_reset_tmds_in_range; | ||
105 | |||
106 | /* Reset PHY automatically when TMDS clock is detected. | ||
107 | * Sets PHY_AUTO_RST4 in register PHY_CTL2. | ||
108 | * Default: false | ||
109 | */ | ||
110 | bool hdmi_phy_auto_reset_tmds_valid; | ||
111 | |||
112 | /* Reset HDMI PHY automatically when hsync period is out of range. | ||
113 | * Sets H_PI_RST in register HV_RST. | ||
114 | * Default: false | ||
115 | */ | ||
116 | bool hdmi_phy_auto_reset_hsync_out_of_range; | ||
117 | |||
118 | /* Reset HDMI PHY automatically when vsync period is out of range. | ||
119 | * Sets V_PI_RST in register HV_RST. | ||
120 | * Default: false | ||
121 | */ | ||
122 | bool hdmi_phy_auto_reset_vsync_out_of_range; | ||
123 | }; | ||
124 | |||
125 | /* custom controls */ | ||
126 | /* Audio sample rate in Hz */ | ||
127 | #define TC358743_CID_AUDIO_SAMPLING_RATE (V4L2_CID_USER_TC358743_BASE + 0) | ||
128 | /* Audio present status */ | ||
129 | #define TC358743_CID_AUDIO_PRESENT (V4L2_CID_USER_TC358743_BASE + 1) | ||
130 | |||
131 | #endif | ||
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 9f6e108ff4a0..d448c536b49d 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h | |||
@@ -174,6 +174,10 @@ enum v4l2_colorfx { | |||
174 | * We reserve 16 controls for this driver. */ | 174 | * We reserve 16 controls for this driver. */ |
175 | #define V4L2_CID_USER_ADV7180_BASE (V4L2_CID_USER_BASE + 0x1070) | 175 | #define V4L2_CID_USER_ADV7180_BASE (V4L2_CID_USER_BASE + 0x1070) |
176 | 176 | ||
177 | /* The base for the tc358743 driver controls. | ||
178 | * We reserve 16 controls for this driver. */ | ||
179 | #define V4L2_CID_USER_TC358743_BASE (V4L2_CID_USER_BASE + 0x1080) | ||
180 | |||
177 | /* MPEG-class control IDs */ | 181 | /* MPEG-class control IDs */ |
178 | /* The MPEG controls are applicable to all codec controls | 182 | /* The MPEG controls are applicable to all codec controls |
179 | * and the 'MPEG' part of the define is historical */ | 183 | * and the 'MPEG' part of the define is historical */ |