1 /* linux/drivers/media/video/samsung/tvout/hw_if/hdmi.c
3 * Copyright (c) 2009 Samsung Electronics
4 * http://www.samsung.com/
6 * Functions for HDMI of Samsung TVOUT driver
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 #include <linux/delay.h>
17 #include <mach/regs-hdmi.h>
19 #ifdef CONFIG_CPU_S5PV210
23 #include "../s5p_tvout_common_lib.h"
28 #ifdef CONFIG_HDMI_DEBUG
29 #define tvout_dbg(fmt, ...) \
30 printk(KERN_INFO "\t\t[HDMI] %s(): " fmt, \
31 __func__, ##__VA_ARGS__)
33 #define tvout_dbg(fmt, ...)
37 /****************************************
38 * Definitions for HDMI_PHY
39 ***************************************/
41 #define PHY_I2C_ADDRESS 0x70
42 #define PHY_REG_MODE_SET_DONE 0x1F
44 #define I2C_ACK (1 << 7)
45 #define I2C_INT (1 << 5)
46 #define I2C_PEND (1 << 4)
47 #define I2C_INT_CLEAR (0 << 4)
48 #define I2C_CLK (0x41)
49 #define I2C_CLK_PEND_INT (I2C_CLK | I2C_INT_CLEAR | I2C_INT)
50 #define I2C_ENABLE (1 << 4)
51 #define I2C_START (1 << 5)
52 #define I2C_MODE_MTX 0xC0
53 #define I2C_MODE_MRX 0x80
57 #define STATE_TX_EDDC_SEGADDR 1
58 #define STATE_TX_EDDC_SEGNUM 2
59 #define STATE_TX_DDC_ADDR 3
60 #define STATE_TX_DDC_OFFSET 4
61 #define STATE_RX_DDC_ADDR 5
62 #define STATE_RX_DDC_DATA 6
63 #define STATE_RX_ADDR 7
64 #define STATE_RX_DATA 8
65 #define STATE_TX_ADDR 9
66 #define STATE_TX_DATA 10
67 #define STATE_TX_STOP 11
68 #define STATE_RX_STOP 12
77 } i2c_hdmi_phy_context;
82 /****************************************
83 * Definitions for HDMI
84 ***************************************/
85 #define HDMI_IRQ_TOTAL_NUM 6
88 /* private data area */
89 void __iomem *hdmi_base;
90 void __iomem *i2c_hdmi_phy_base;
92 irqreturn_t (*s5p_hdmi_isr_ftn[HDMI_IRQ_TOTAL_NUM])(int irq, void *);
95 static const u8 phy_config[][3][32] = {
96 { /* freq = 25.200 MHz */
98 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
99 0x6B, 0x10, 0x02, 0x51, 0x5f, 0xF1, 0x54, 0x7e,
100 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
101 0x22, 0x40, 0xf3, 0x26, 0x00, 0x00, 0x00, 0x80,
103 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
104 0x6B, 0x10, 0x02, 0x51, 0x9f, 0xF6, 0x54, 0x9e,
105 0x84, 0x00, 0x32, 0x38, 0x00, 0xB8, 0x10, 0xE0,
106 0x22, 0x40, 0xc2, 0x26, 0x00, 0x00, 0x00, 0x80,
108 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
109 0x6B, 0x10, 0x02, 0x51, 0xFf, 0xF3, 0x54, 0xbd,
110 0x84, 0x00, 0x30, 0x38, 0x00, 0xA4, 0x10, 0xE0,
111 0x22, 0x40, 0xa2, 0x26, 0x00, 0x00, 0x00, 0x80,
113 }, { /* freq = 25.175 MHz */
115 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x1e, 0x20,
116 0x6B, 0x50, 0x10, 0x51, 0xf1, 0x31, 0x54, 0xbd,
117 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
118 0x22, 0x40, 0xf3, 0x26, 0x00, 0x00, 0x00, 0x80,
120 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x2b, 0x40,
121 0x6B, 0x50, 0x10, 0x51, 0xF2, 0x32, 0x54, 0xec,
122 0x84, 0x00, 0x10, 0x38, 0x00, 0xB8, 0x10, 0xE0,
123 0x22, 0x40, 0xc2, 0x26, 0x00, 0x00, 0x00, 0x80,
125 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x1e, 0x20,
126 0x6B, 0x10, 0x02, 0x51, 0xf1, 0x31, 0x54, 0xbd,
127 0x84, 0x00, 0x10, 0x38, 0x00, 0xA4, 0x10, 0xE0,
128 0x22, 0x40, 0xa2, 0x26, 0x00, 0x00, 0x00, 0x80,
130 }, { /* freq = 27 MHz */
132 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
133 0x6B, 0x10, 0x02, 0x51, 0xDf, 0xF2, 0x54, 0x87,
134 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
135 0x22, 0x40, 0xe3, 0x26, 0x00, 0x00, 0x00, 0x80,
137 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x02, 0x08,
138 0x6A, 0x10, 0x02, 0x51, 0xCf, 0xF1, 0x54, 0xa9,
139 0x84, 0x00, 0x10, 0x38, 0x00, 0xB8, 0x10, 0xE0,
140 0x22, 0x40, 0xb5, 0x26, 0x00, 0x00, 0x00, 0x80,
142 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xfc, 0x08,
143 0x6B, 0x10, 0x02, 0x51, 0x2f, 0xF2, 0x54, 0xcb,
144 0x84, 0x00, 0x10, 0x38, 0x00, 0xA4, 0x10, 0xE0,
145 0x22, 0x40, 0x97, 0x26, 0x00, 0x00, 0x00, 0x80,
147 }, { /* freq = 27.027 MHz */
149 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
150 0x6B, 0x10, 0x02, 0x51, 0xDf, 0xF2, 0x54, 0x87,
151 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
152 0x22, 0x40, 0xe2, 0x26, 0x00, 0x00, 0x00, 0x80,
154 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x31, 0x50,
155 0x6B, 0x10, 0x02, 0x51, 0x8f, 0xF3, 0x54, 0xa9,
156 0x84, 0x00, 0x30, 0x38, 0x00, 0xB8, 0x10, 0xE0,
157 0x22, 0x40, 0xb5, 0x26, 0x00, 0x00, 0x00, 0x80,
159 0x01, 0x05, 0x00, 0x10, 0x10, 0x9C, 0x1b, 0x64,
160 0x6F, 0x10, 0x02, 0x51, 0x7f, 0xF8, 0x54, 0xcb,
161 0x84, 0x00, 0x32, 0x38, 0x00, 0xA4, 0x10, 0xE0,
162 0x22, 0x40, 0x97, 0x26, 0x00, 0x00, 0x00, 0x80,
164 }, { /* freq = 54 MHz */
166 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
167 0x6B, 0x10, 0x01, 0x51, 0xDf, 0xF2, 0x54, 0x87,
168 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
169 0x22, 0x40, 0xe3, 0x26, 0x01, 0x00, 0x00, 0x80,
171 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x02, 0x08,
172 0x6A, 0x10, 0x01, 0x51, 0xCf, 0xF1, 0x54, 0xa9,
173 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8, 0x10, 0xE0,
174 0x22, 0x40, 0xb5, 0x26, 0x01, 0x00, 0x00, 0x80,
176 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xfc, 0x08,
177 0x6B, 0x10, 0x01, 0x51, 0x2f, 0xF2, 0x54, 0xcb,
178 0x84, 0x00, 0x10, 0x38, 0x00, 0xE4, 0x10, 0xE0,
179 0x22, 0x40, 0x97, 0x26, 0x01, 0x00, 0x00, 0x80,
181 }, { /* freq = 54.054 MHz */
183 0x01, 0x05, 0x00, 0xd4, 0x10, 0x9C, 0x09, 0x64,
184 0x6B, 0x10, 0x01, 0x51, 0xDf, 0xF2, 0x54, 0x87,
185 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
186 0x22, 0x40, 0xe2, 0x26, 0x01, 0x00, 0x00, 0x80,
188 0x01, 0x05, 0x00, 0xd4, 0x10, 0x9C, 0x31, 0x50,
189 0x6B, 0x10, 0x01, 0x51, 0x8f, 0xF3, 0x54, 0xa9,
190 0x84, 0x00, 0x30, 0x38, 0x00, 0xF8, 0x10, 0xE0,
191 0x22, 0x40, 0xb5, 0x26, 0x01, 0x00, 0x00, 0x80,
193 0x01, 0x05, 0x00, 0x10, 0x10, 0x9C, 0x1b, 0x64,
194 0x6F, 0x10, 0x01, 0x51, 0x7f, 0xF8, 0x54, 0xcb,
195 0x84, 0x00, 0x32, 0x38, 0x00, 0xE4, 0x10, 0xE0,
196 0x22, 0x40, 0x97, 0x26, 0x01, 0x00, 0x00, 0x80,
198 }, { /* freq = 74.250 MHz */
200 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
201 0x6A, 0x10, 0x01, 0x51, 0xff, 0xF1, 0x54, 0xba,
202 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
203 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x80,
205 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xd6, 0x40,
206 0x6B, 0x10, 0x01, 0x51, 0x7f, 0xF2, 0x54, 0xe8,
207 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8, 0x10, 0xE0,
208 0x22, 0x40, 0x83, 0x26, 0x01, 0x00, 0x00, 0x80,
210 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x34, 0x40,
211 0x6B, 0x10, 0x01, 0x51, 0xef, 0xF2, 0x54, 0x16,
212 0x85, 0x00, 0x10, 0x38, 0x00, 0xE4, 0x10, 0xE0,
213 0x22, 0x40, 0xdc, 0x26, 0x02, 0x00, 0x00, 0x80,
215 }, { /* freq = 74.176 MHz */
217 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
218 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
219 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
220 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x80,
222 0x01, 0x05, 0x00, 0x10, 0x10, 0x9C, 0xab, 0x5B,
223 0x6F, 0x10, 0x01, 0x51, 0xbf, 0xF9, 0x54, 0xe8,
224 0x84, 0x00, 0x32, 0x38, 0x00, 0xF8, 0x10, 0xE0,
225 0x22, 0x40, 0x84, 0x26, 0x01, 0x00, 0x00, 0x80,
227 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0xcd, 0x5B,
228 0x6F, 0x10, 0x01, 0x51, 0xdf, 0xF5, 0x54, 0x16,
229 0x85, 0x00, 0x30, 0x38, 0x00, 0xE4, 0x10, 0xE0,
230 0x22, 0x40, 0xdc, 0x26, 0x02, 0x00, 0x00, 0x80,
232 }, { /* freq = 148.500 MHz - Pre-emph + Higher Tx amp. */
234 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
235 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
236 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
237 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x80,
239 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xd6, 0x40,
240 0x6B, 0x18, 0x00, 0x51, 0x7f, 0xF2, 0x54, 0xe8,
241 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8, 0x10, 0xE0,
242 0x23, 0x41, 0x83, 0x26, 0x02, 0x00, 0x00, 0x80,
244 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x34, 0x40,
245 0x6B, 0x18, 0x00, 0x51, 0xef, 0xF2, 0x54, 0x16,
246 0x85, 0x00, 0x10, 0x38, 0x00, 0xE4, 0x10, 0xE0,
247 0x23, 0x41, 0x6d, 0x26, 0x02, 0x00, 0x00, 0x80,
249 }, { /* freq = 148.352 MHz */
251 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
252 0x6D, 0x18, 0x00, 0x51, 0xef, 0xF3, 0x54, 0xb9,
253 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
254 0x22, 0x40, 0xa5, 0x26, 0x02, 0x00, 0x00, 0x80,
256 0x01, 0x05, 0x00, 0x10, 0x10, 0x9C, 0xab, 0x5B,
257 0x6F, 0x18, 0x00, 0x51, 0xbf, 0xF9, 0x54, 0xe8,
258 0x84, 0x00, 0x32, 0x38, 0x00, 0xF8, 0x10, 0xE0,
259 0x23, 0x41, 0x84, 0x26, 0x02, 0x00, 0x00, 0x80,
261 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0xcd, 0x5B,
262 0x6F, 0x18, 0x00, 0x51, 0xdf, 0xF5, 0x54, 0x16,
263 0x85, 0x00, 0x30, 0x38, 0x00, 0xE4, 0x10, 0xE0,
264 0x23, 0x41, 0x6d, 0x26, 0x02, 0x00, 0x00, 0x80,
266 }, { /* freq = 108.108 MHz */
268 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
269 0x6B, 0x18, 0x00, 0x51, 0xDf, 0xF2, 0x54, 0x87,
270 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
271 0x22, 0x40, 0xe2, 0x26, 0x02, 0x00, 0x00, 0x80,
273 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x31, 0x50,
274 0x6D, 0x18, 0x00, 0x51, 0x8f, 0xF3, 0x54, 0xa9,
275 0x84, 0x00, 0x30, 0x38, 0x00, 0xF8, 0x10, 0xE0,
276 0x22, 0x40, 0xb5, 0x26, 0x02, 0x00, 0x00, 0x80,
278 0x01, 0x05, 0x00, 0x10, 0x10, 0x9C, 0x1b, 0x64,
279 0x6F, 0x18, 0x00, 0x51, 0x7f, 0xF8, 0x54, 0xcb,
280 0x84, 0x00, 0x32, 0x38, 0x00, 0xE4, 0x10, 0xE0,
281 0x22, 0x40, 0x97, 0x26, 0x02, 0x00, 0x00, 0x80,
283 }, { /* freq = 72 MHz */
285 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
286 0x6B, 0x10, 0x01, 0x51, 0xEf, 0xF1, 0x54, 0xb4,
287 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
288 0x22, 0x40, 0xaa, 0x26, 0x01, 0x00, 0x00, 0x80,
290 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
291 0x6F, 0x10, 0x01, 0x51, 0xBf, 0xF4, 0x54, 0xe1,
292 0x84, 0x00, 0x30, 0x38, 0x00, 0xF8, 0x10, 0xE0,
293 0x22, 0x40, 0x88, 0x26, 0x01, 0x00, 0x00, 0x80,
295 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
296 0x6B, 0x18, 0x00, 0x51, 0xDf, 0xF2, 0x54, 0x87,
297 0x84, 0x00, 0x30, 0x38, 0x00, 0xE4, 0x10, 0xE0,
298 0x22, 0x40, 0xe3, 0x26, 0x02, 0x00, 0x00, 0x80,
300 }, { /* freq = 25 MHz */
302 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x20, 0x40,
303 0x6B, 0x50, 0x10, 0x51, 0xff, 0xF1, 0x54, 0xbc,
304 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
305 0x22, 0x40, 0xf5, 0x26, 0x00, 0x00, 0x00, 0x80,
307 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x08, 0x40,
308 0x6B, 0x50, 0x10, 0x51, 0x7f, 0xF2, 0x54, 0xea,
309 0x84, 0x00, 0x10, 0x38, 0x00, 0xB8, 0x10, 0xE0,
310 0x22, 0x40, 0xc4, 0x26, 0x00, 0x00, 0x00, 0x80,
312 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x20, 0x40,
313 0x6B, 0x10, 0x02, 0x51, 0xff, 0xF1, 0x54, 0xbc,
314 0x84, 0x00, 0x10, 0x38, 0x00, 0xA4, 0x10, 0xE0,
315 0x22, 0x40, 0xa3, 0x26, 0x00, 0x00, 0x00, 0x80,
317 }, { /* freq = 65 MHz */
319 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x02, 0x0c,
320 0x6B, 0x10, 0x01, 0x51, 0xBf, 0xF1, 0x54, 0xa3,
321 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
322 0x22, 0x40, 0xbc, 0x26, 0x01, 0x00, 0x00, 0x80,
324 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf2, 0x30,
325 0x6A, 0x10, 0x01, 0x51, 0x2f, 0xF2, 0x54, 0xcb,
326 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8, 0x10, 0xE0,
327 0x22, 0x40, 0x96, 0x26, 0x01, 0x00, 0x00, 0x80,
329 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xd0, 0x40,
330 0x6B, 0x10, 0x01, 0x51, 0x9f, 0xF2, 0x54, 0xf4,
331 0x84, 0x00, 0x10, 0x38, 0x00, 0xE4, 0x10, 0xE0,
332 0x22, 0x40, 0x7D, 0x26, 0x01, 0x00, 0x00, 0x80,
334 }, { /* freq = 108 MHz */
336 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
337 0x6D, 0x18, 0x00, 0x51, 0xDf, 0xF2, 0x54, 0x87,
338 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
339 0x22, 0x40, 0xe3, 0x26, 0x02, 0x00, 0x00, 0x80,
341 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x02, 0x08,
342 0x6A, 0x18, 0x00, 0x51, 0xCf, 0xF1, 0x54, 0xa9,
343 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8, 0x10, 0xE0,
344 0x22, 0x40, 0xb5, 0x26, 0x02, 0x00, 0x00, 0x80,
346 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xfc, 0x08,
347 0x6B, 0x18, 0x00, 0x51, 0x2f, 0xF2, 0x54, 0xcb,
348 0x84, 0x00, 0x10, 0x38, 0x00, 0xE4, 0x10, 0xE0,
349 0x22, 0x40, 0x97, 0x26, 0x02, 0x00, 0x00, 0x80,
351 }, { /* freq = 162 MHz */
353 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
354 0x6F, 0x18, 0x00, 0x51, 0x7f, 0xF8, 0x54, 0xcb,
355 0x84, 0x00, 0x32, 0x38, 0x00, 0x08, 0x10, 0xE0,
356 0x22, 0x40, 0x97, 0x26, 0x02, 0x00, 0x00, 0x80,
358 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0x18, 0x40,
359 0x6B, 0x18, 0x00, 0x51, 0xAf, 0xF2, 0x54, 0xfd,
360 0x84, 0x00, 0x10, 0x38, 0x00, 0xF8, 0x10, 0xE0,
361 0x23, 0x41, 0x78, 0x26, 0x02, 0x00, 0x00, 0x80,
363 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xd0, 0x40,
364 0x6B, 0x18, 0x00, 0x51, 0x3f, 0xF3, 0x54, 0x30,
365 0x85, 0x00, 0x10, 0x38, 0x00, 0xE4, 0x10, 0xE0,
366 0x23, 0x41, 0x64, 0x26, 0x02, 0x00, 0x00, 0x80,
372 static void s5p_hdmi_reg_core_reset(void)
374 writeb(0x0, hdmi_base + S5P_HDMI_CORE_RSTOUT);
378 writeb(0x1, hdmi_base + S5P_HDMI_CORE_RSTOUT);
381 static s32 s5p_hdmi_i2c_phy_interruptwait(void)
387 status = readb(i2c_hdmi_phy_base + HDMI_I2C_CON);
389 if (status & I2C_PEND) {
390 reg = readb(i2c_hdmi_phy_base + HDMI_I2C_STAT);
399 static s32 s5p_hdmi_i2c_phy_read(u8 addr, u8 nbytes, u8 *buffer)
405 i2c_hdmi_phy_context.state = STATE_RX_ADDR;
406 i2c_hdmi_phy_context.buffer = buffer;
407 i2c_hdmi_phy_context.bytes = nbytes;
409 writeb(I2C_CLK | I2C_INT | I2C_ACK, i2c_hdmi_phy_base + HDMI_I2C_CON);
410 writeb(I2C_ENABLE | I2C_MODE_MRX, i2c_hdmi_phy_base + HDMI_I2C_STAT);
411 writeb(addr & 0xFE, i2c_hdmi_phy_base + HDMI_I2C_DS);
412 writeb(I2C_ENABLE | I2C_START | I2C_MODE_MRX,
413 i2c_hdmi_phy_base + HDMI_I2C_STAT);
417 if (i2c_hdmi_phy_context.state != STATE_RX_STOP) {
419 if (s5p_hdmi_i2c_phy_interruptwait() != 0) {
420 tvout_err("interrupt wait failed!!!\n");
427 switch (i2c_hdmi_phy_context.state) {
429 reg = readb(i2c_hdmi_phy_base + HDMI_I2C_DS);
430 *(i2c_hdmi_phy_context.buffer) = reg;
432 i2c_hdmi_phy_context.buffer++;
433 --(i2c_hdmi_phy_context.bytes);
435 if (i2c_hdmi_phy_context.bytes == 1) {
436 i2c_hdmi_phy_context.state = STATE_RX_STOP;
437 writeb(I2C_CLK_PEND_INT,
438 i2c_hdmi_phy_base + HDMI_I2C_CON);
440 writeb(I2C_CLK_PEND_INT | I2C_ACK,
441 i2c_hdmi_phy_base + HDMI_I2C_CON);
447 i2c_hdmi_phy_context.state = STATE_RX_DATA;
449 if (i2c_hdmi_phy_context.bytes == 1) {
450 i2c_hdmi_phy_context.state = STATE_RX_STOP;
451 writeb(I2C_CLK_PEND_INT,
452 i2c_hdmi_phy_base + HDMI_I2C_CON);
454 writeb(I2C_CLK_PEND_INT | I2C_ACK,
455 i2c_hdmi_phy_base + HDMI_I2C_CON);
461 i2c_hdmi_phy_context.state = STATE_IDLE;
463 reg = readb(i2c_hdmi_phy_base + HDMI_I2C_DS);
465 *(i2c_hdmi_phy_context.buffer) = reg;
467 writeb(I2C_MODE_MRX|I2C_ENABLE,
468 i2c_hdmi_phy_base + HDMI_I2C_STAT);
469 writeb(I2C_CLK_PEND_INT,
470 i2c_hdmi_phy_base + HDMI_I2C_CON);
472 i2c_hdmi_phy_base + HDMI_I2C_STAT);
474 while (readb(i2c_hdmi_phy_base + HDMI_I2C_STAT) &
483 tvout_err("error state!!!\n");
496 static s32 s5p_hdmi_i2c_phy_write(u8 addr, u8 nbytes, u8 *buffer)
502 i2c_hdmi_phy_context.state = STATE_TX_ADDR;
503 i2c_hdmi_phy_context.buffer = buffer;
504 i2c_hdmi_phy_context.bytes = nbytes;
506 writeb(I2C_CLK | I2C_INT | I2C_ACK, i2c_hdmi_phy_base + HDMI_I2C_CON);
507 writeb(I2C_ENABLE | I2C_MODE_MTX, i2c_hdmi_phy_base + HDMI_I2C_STAT);
508 writeb(addr & 0xFE, i2c_hdmi_phy_base + HDMI_I2C_DS);
509 writeb(I2C_ENABLE | I2C_START | I2C_MODE_MTX,
510 i2c_hdmi_phy_base + HDMI_I2C_STAT);
514 if (s5p_hdmi_i2c_phy_interruptwait() != 0) {
515 tvout_err("interrupt wait failed!!!\n");
521 switch (i2c_hdmi_phy_context.state) {
524 i2c_hdmi_phy_context.state = STATE_TX_DATA;
526 reg = *(i2c_hdmi_phy_context.buffer);
528 writeb(reg, i2c_hdmi_phy_base + HDMI_I2C_DS);
530 i2c_hdmi_phy_context.buffer++;
531 --(i2c_hdmi_phy_context.bytes);
533 if (i2c_hdmi_phy_context.bytes == 0) {
534 i2c_hdmi_phy_context.state = STATE_TX_STOP;
535 writeb(I2C_CLK_PEND_INT,
536 i2c_hdmi_phy_base + HDMI_I2C_CON);
538 writeb(I2C_CLK_PEND_INT | I2C_ACK,
539 i2c_hdmi_phy_base + HDMI_I2C_CON);
545 i2c_hdmi_phy_context.state = STATE_IDLE;
547 writeb(I2C_MODE_MTX | I2C_ENABLE,
548 i2c_hdmi_phy_base + HDMI_I2C_STAT);
549 writeb(I2C_CLK_PEND_INT,
550 i2c_hdmi_phy_base + HDMI_I2C_CON);
552 i2c_hdmi_phy_base + HDMI_I2C_STAT);
554 while (readb(i2c_hdmi_phy_base + HDMI_I2C_STAT) &
563 tvout_err("error state!!!\n");
576 #ifdef CONFIG_SND_S5P_SPDIF
577 static void s5p_hdmi_audio_set_config(
578 enum s5p_tvout_audio_codec_type audio_codec)
580 u32 data_type = (audio_codec == PCM) ?
581 S5P_HDMI_SPDIFIN_CFG_LINEAR_PCM_TYPE :
582 (audio_codec == AC3) ?
583 S5P_HDMI_SPDIFIN_CFG_NO_LINEAR_PCM_TYPE : 0xff;
585 tvout_dbg("audio codec type = %s\n",
586 (audio_codec & PCM) ? "PCM" :
587 (audio_codec & AC3) ? "AC3" :
588 (audio_codec & MP3) ? "MP3" :
589 (audio_codec & WMA) ? "WMA" : "Unknown");
591 /* open SPDIF path on HDMI_I2S */
592 writeb(S5P_HDMI_I2S_CLK_EN, hdmi_base + S5P_HDMI_I2S_CLK_CON);
593 writeb(readl(hdmi_base + S5P_HDMI_I2S_MUX_CON) |
594 S5P_HDMI_I2S_CUV_I2S_ENABLE |
595 S5P_HDMI_I2S_MUX_ENABLE,
596 hdmi_base + S5P_HDMI_I2S_MUX_CON);
597 writeb(S5P_HDMI_I2S_CH_ALL_EN, hdmi_base + S5P_HDMI_I2S_MUX_CH);
598 writeb(S5P_HDMI_I2S_CUV_RL_EN, hdmi_base + S5P_HDMI_I2S_MUX_CUV);
600 writeb(S5P_HDMI_SPDIFIN_CFG_FILTER_2_SAMPLE | data_type |
601 S5P_HDMI_SPDIFIN_CFG_PCPD_MANUAL_SET |
602 S5P_HDMI_SPDIFIN_CFG_WORD_LENGTH_M_SET |
603 S5P_HDMI_SPDIFIN_CFG_U_V_C_P_REPORT |
604 S5P_HDMI_SPDIFIN_CFG_BURST_SIZE_2 |
605 S5P_HDMI_SPDIFIN_CFG_DATA_ALIGN_32BIT,
606 hdmi_base + S5P_HDMI_SPDIFIN_CONFIG_1);
608 writeb(S5P_HDMI_SPDIFIN_CFG2_NO_CLK_DIV,
609 hdmi_base + S5P_HDMI_SPDIFIN_CONFIG_2);
612 static void s5p_hdmi_audio_clock_enable(void)
614 writeb(S5P_HDMI_SPDIFIN_CLK_ON, hdmi_base + S5P_HDMI_SPDIFIN_CLK_CTRL);
615 writeb(S5P_HDMI_SPDIFIN_STATUS_CHK_OP_MODE,
616 hdmi_base + S5P_HDMI_SPDIFIN_OP_CTRL);
619 static void s5p_hdmi_audio_set_repetition_time(
620 enum s5p_tvout_audio_codec_type audio_codec,
621 u32 bits, u32 frame_size_code)
623 /* Only 4'b1011 24bit */
625 u32 rpt_cnt = (audio_codec == AC3) ? 1536 * 2 - 1 : 0;
627 tvout_dbg("repetition count = %d\n", rpt_cnt);
629 /* 24bit and manual mode */
630 writeb(((rpt_cnt & 0xf) << 4) | wl,
631 hdmi_base + S5P_HDMI_SPDIFIN_USER_VALUE_1);
632 /* if PCM this value is 0 */
633 writeb((rpt_cnt >> 4) & 0xff,
634 hdmi_base + S5P_HDMI_SPDIFIN_USER_VALUE_2);
635 /* if PCM this value is 0 */
636 writeb(frame_size_code & 0xff,
637 hdmi_base + S5P_HDMI_SPDIFIN_USER_VALUE_3);
638 /* if PCM this value is 0 */
639 writeb((frame_size_code >> 8) & 0xff,
640 hdmi_base + S5P_HDMI_SPDIFIN_USER_VALUE_4);
643 static void s5p_hdmi_audio_irq_enable(u32 irq_en)
645 writeb(irq_en, hdmi_base + S5P_HDMI_SPDIFIN_IRQ_MASK);
648 static void s5p_hdmi_audio_i2s_config(
649 enum s5p_tvout_audio_codec_type audio_codec,
650 u32 sample_rate, u32 bits_per_sample,
653 u32 data_num, bit_ch, sample_frq;
655 if (bits_per_sample == 20) {
658 } else if (bits_per_sample == 24) {
666 writeb((S5P_HDMI_I2S_IN_DISABLE | S5P_HDMI_I2S_AUD_I2S |
667 S5P_HDMI_I2S_CUV_I2S_ENABLE | S5P_HDMI_I2S_MUX_ENABLE),
668 hdmi_base + S5P_HDMI_I2S_MUX_CON);
670 writeb(S5P_HDMI_I2S_CH0_EN | S5P_HDMI_I2S_CH1_EN | S5P_HDMI_I2S_CH2_EN,
671 hdmi_base + S5P_HDMI_I2S_MUX_CH);
673 writeb(S5P_HDMI_I2S_CUV_RL_EN, hdmi_base + S5P_HDMI_I2S_MUX_CUV);
675 sample_frq = (sample_rate == 44100) ? 0 :
676 (sample_rate == 48000) ? 2 :
677 (sample_rate == 32000) ? 3 :
678 (sample_rate == 96000) ? 0xa : 0x0;
680 /* readl(hdmi_base + S5P_HDMI_YMAX) */
681 writeb(S5P_HDMI_I2S_CLK_DIS, hdmi_base + S5P_HDMI_I2S_CLK_CON);
682 writeb(S5P_HDMI_I2S_CLK_EN, hdmi_base + S5P_HDMI_I2S_CLK_CON);
684 writeb(readl(hdmi_base + S5P_HDMI_I2S_DSD_CON) | 0x01,
685 hdmi_base + S5P_HDMI_I2S_DSD_CON);
687 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
688 writeb(S5P_HDMI_I2S_SEL_SCLK(5) | S5P_HDMI_I2S_SEL_LRCK(6),
689 hdmi_base + S5P_HDMI_I2S_PIN_SEL_0);
690 writeb(S5P_HDMI_I2S_SEL_SDATA1(1) | S5P_HDMI_I2S_SEL_SDATA2(4),
691 hdmi_base + S5P_HDMI_I2S_PIN_SEL_1);
692 writeb(S5P_HDMI_I2S_SEL_SDATA3(1) | S5P_HDMI_I2S_SEL_SDATA2(2),
693 hdmi_base + S5P_HDMI_I2S_PIN_SEL_2);
694 writeb(S5P_HDMI_I2S_SEL_DSD(0), hdmi_base + S5P_HDMI_I2S_PIN_SEL_3);
697 writeb(S5P_HDMI_I2S_SCLK_RISING_EDGE | S5P_HDMI_I2S_L_CH_LOW_POL,
698 hdmi_base + S5P_HDMI_I2S_CON_1);
699 writeb(S5P_HDMI_I2S_MSB_FIRST_MODE |
700 S5P_HDMI_I2S_SET_BIT_CH(bit_ch) |
701 S5P_HDMI_I2S_SET_SDATA_BIT(data_num) |
702 S5P_HDMI_I2S_BASIC_FORMAT,
703 hdmi_base + S5P_HDMI_I2S_CON_2);
705 /* Configure register related to CUV information */
706 writeb(S5P_HDMI_I2S_CH_STATUS_MODE_0 |
707 S5P_HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH |
708 S5P_HDMI_I2S_COPYRIGHT |
709 S5P_HDMI_I2S_LINEAR_PCM |
710 S5P_HDMI_I2S_CONSUMER_FORMAT,
711 hdmi_base + S5P_HDMI_I2S_CH_ST_0);
712 writeb(S5P_HDMI_I2S_CD_PLAYER,
713 hdmi_base + S5P_HDMI_I2S_CH_ST_1);
714 writeb(S5P_HDMI_I2S_SET_SOURCE_NUM(0),
715 hdmi_base + S5P_HDMI_I2S_CH_ST_2);
716 writeb(S5P_HDMI_I2S_CLK_ACCUR_LEVEL_2 |
717 S5P_HDMI_I2S_SET_SAMPLING_FREQ(sample_frq),
718 hdmi_base + S5P_HDMI_I2S_CH_ST_3);
719 writeb(S5P_HDMI_I2S_ORG_SAMPLING_FREQ_44_1 |
720 S5P_HDMI_I2S_WORD_LENGTH_MAX24_24BITS |
721 S5P_HDMI_I2S_WORD_LENGTH_MAX_24BITS,
722 hdmi_base + S5P_HDMI_I2S_CH_ST_4);
724 writeb(S5P_HDMI_I2S_CH_STATUS_RELOAD,
725 hdmi_base + S5P_HDMI_I2S_CH_ST_CON);
729 static u8 s5p_hdmi_checksum(int sum, int size, u8 *data)
733 for (i = 0; i < size; i++)
734 sum += (u32)(data[i]);
736 return (u8)(0x100 - (sum & 0xff));
740 static int s5p_hdmi_phy_control(bool on, u8 addr, u8 offset, u8 *read_buffer)
745 buff[1] = (on) ? (read_buffer[addr] & (~(1 << offset))) :
746 (read_buffer[addr] | (1 << offset));
748 if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buff) != 0)
754 static bool s5p_hdmi_phy_is_enable(void)
758 #ifdef CONFIG_CPU_S5PV310
759 reg = readl(S5PV310_VA_PMU + 0x0700);
762 #ifdef CONFIG_CPU_S5PV210
763 reg = readl(S3C_VA_SYS + 0xE804);
766 return reg & (1 << 0);
769 static void s5p_hdmi_phy_enable(bool on)
773 #ifdef CONFIG_CPU_S5PV310
774 reg = readl(S5PV310_VA_PMU + 0x0700);
781 writeb(reg, S5PV310_VA_PMU + 0x0700);
784 #ifdef CONFIG_CPU_S5PV210
785 reg = readl(S3C_VA_SYS + 0xE804);
792 writeb(reg, S3C_VA_SYS + 0xE804);
796 int s5p_hdmi_phy_power(bool on)
800 u8 read_buffer[0x40] = {0, };
802 size = sizeof(phy_config[0][0])
803 / sizeof(phy_config[0][0][0]);
805 buffer = (u8 *) phy_config[0][0];
808 if (!s5p_hdmi_phy_is_enable()) {
809 s5p_hdmi_phy_enable(1);
811 if (s5p_hdmi_i2c_phy_write(
812 PHY_I2C_ADDRESS, 1, buffer) != 0)
815 if (s5p_hdmi_i2c_phy_read(
816 PHY_I2C_ADDRESS, size, read_buffer) != 0) {
817 tvout_err("s5p_hdmi_i2c_phy_read failed.\n");
821 s5p_hdmi_phy_control(true, 0x1, 0x5, read_buffer);
822 s5p_hdmi_phy_control(true, 0x1, 0x7, read_buffer);
823 s5p_hdmi_phy_control(true, 0x5, 0x5, read_buffer);
824 s5p_hdmi_phy_control(true, 0x17, 0x0, read_buffer);
825 s5p_hdmi_phy_control(true, 0x17, 0x1, read_buffer);
828 if (s5p_hdmi_phy_is_enable()) {
829 if (s5p_hdmi_i2c_phy_write(
830 PHY_I2C_ADDRESS, 1, buffer) != 0)
833 if (s5p_hdmi_i2c_phy_read(
834 PHY_I2C_ADDRESS, size, read_buffer) != 0) {
835 tvout_err("s5p_hdmi_i2c_phy_read failed.\n");
839 s5p_hdmi_phy_control(false, 0x1, 0x5, read_buffer);
840 s5p_hdmi_phy_control(false, 0x1, 0x7, read_buffer);
841 s5p_hdmi_phy_control(false, 0x5, 0x5, read_buffer);
842 s5p_hdmi_phy_control(false, 0x17, 0x0, read_buffer);
843 s5p_hdmi_phy_control(false, 0x17, 0x1, read_buffer);
845 s5p_hdmi_phy_enable(0);
855 s32 s5p_hdmi_phy_config(
856 enum phy_freq freq, enum s5p_hdmi_color_depth cd)
860 u8 buffer[32] = {0, };
880 buffer[0] = PHY_REG_MODE_SET_DONE;
883 if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 2, buffer) != 0) {
884 tvout_err("s5p_hdmi_i2c_phy_write failed.\n");
888 writeb(0x5, i2c_hdmi_phy_base + HDMI_I2C_LC);
890 size = sizeof(phy_config[freq][index])
891 / sizeof(phy_config[freq][index][0]);
893 memcpy(buffer, phy_config[freq][index], sizeof(buffer));
895 if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, size, buffer) != 0)
900 if (s5p_hdmi_i2c_phy_write(PHY_I2C_ADDRESS, 1, buffer) != 0) {
901 tvout_err("s5p_hdmi_i2c_phy_write failed.\n");
905 #ifdef S5P_HDMI_DEBUG
908 u8 read_buffer[0x40] = {0, };
911 if (s5p_hdmi_i2c_phy_read(PHY_I2C_ADDRESS, size, read_buffer) != 0) {
912 tvout_err("s5p_hdmi_i2c_phy_read failed.\n");
916 tvout_dbg("read buffer :\n\t\t");
918 for (i = 1; i < size; i++) {
919 printk("0x%02x", read_buffer[i]);
929 s5p_hdmi_reg_core_reset();
932 reg = readb(hdmi_base + S5P_HDMI_PHY_STATUS);
933 } while (!(reg & S5P_HDMI_PHY_STATUS_READY));
935 writeb(I2C_CLK_PEND_INT, i2c_hdmi_phy_base + HDMI_I2C_CON);
936 writeb(I2C_IDLE, i2c_hdmi_phy_base + HDMI_I2C_STAT);
943 void s5p_hdmi_set_gcp(enum s5p_hdmi_color_depth depth, u8 *gcp)
947 gcp[1] = S5P_HDMI_GCP_48BPP; break;
949 gcp[1] = S5P_HDMI_GCP_36BPP; break;
951 gcp[1] = S5P_HDMI_GCP_30BPP; break;
953 gcp[1] = S5P_HDMI_GCP_24BPP; break;
960 void s5p_hdmi_reg_acr(u8 *acr)
962 u32 n = acr[4] << 16 | acr[5] << 8 | acr[6];
963 u32 cts = acr[1] << 16 | acr[2] << 8 | acr[3];
965 hdmi_write_24(n, hdmi_base + S5P_HDMI_ACR_N0);
966 hdmi_write_24(cts, hdmi_base + S5P_HDMI_ACR_MCTS0);
967 hdmi_write_24(cts, hdmi_base + S5P_HDMI_ACR_CTS0);
969 writeb(4, hdmi_base + S5P_HDMI_ACR_CON);
972 void s5p_hdmi_reg_asp(u8 *asp)
974 writeb(S5P_HDMI_AUD_NO_DST_DOUBLE | S5P_HDMI_AUD_TYPE_SAMPLE |
975 S5P_HDMI_AUD_MODE_TWO_CH | S5P_HDMI_AUD_SP_ALL_DIS,
976 hdmi_base + S5P_HDMI_ASP_CON);
978 writeb(S5P_HDMI_ASP_SP_FLAT_AUD_SAMPLE,
979 hdmi_base + S5P_HDMI_ASP_SP_FLAT);
981 writeb(S5P_HDMI_SPK0R_SEL_I_PCM0R | S5P_HDMI_SPK0L_SEL_I_PCM0L,
982 hdmi_base + S5P_HDMI_ASP_CHCFG0);
983 writeb(S5P_HDMI_SPK0R_SEL_I_PCM0R | S5P_HDMI_SPK0L_SEL_I_PCM0L,
984 hdmi_base + S5P_HDMI_ASP_CHCFG1);
985 writeb(S5P_HDMI_SPK0R_SEL_I_PCM0R | S5P_HDMI_SPK0L_SEL_I_PCM0L,
986 hdmi_base + S5P_HDMI_ASP_CHCFG2);
987 writeb(S5P_HDMI_SPK0R_SEL_I_PCM0R | S5P_HDMI_SPK0L_SEL_I_PCM0L,
988 hdmi_base + S5P_HDMI_ASP_CHCFG3);
991 void s5p_hdmi_reg_gcp(u8 i_p, u8 *gcp)
995 writeb(gcp[2], hdmi_base + S5P_HDMI_GCP_BYTE2);
997 gcp_con = readb(hdmi_base + S5P_HDMI_GCP_CON);
1000 gcp_con |= S5P_HDMI_GCP_CON_EN_1ST_VSYNC |
1001 S5P_HDMI_GCP_CON_EN_2ST_VSYNC;
1003 gcp_con &= (~(S5P_HDMI_GCP_CON_EN_1ST_VSYNC |
1004 S5P_HDMI_GCP_CON_EN_2ST_VSYNC));
1006 writeb(gcp_con, hdmi_base + S5P_HDMI_GCP_CON);
1010 void s5p_hdmi_reg_acp(u8 *header, u8 *acp)
1012 writeb(header[1], hdmi_base + S5P_HDMI_ACP_TYPE);
1015 void s5p_hdmi_reg_isrc(u8 *isrc1, u8 *isrc2)
1019 void s5p_hdmi_reg_gmp(u8 *gmp)
1023 void s5p_hdmi_reg_infoframe(struct s5p_hdmi_infoframe *info, u8 *data)
1025 u32 start_addr = 0, sum_addr = 0;
1028 switch (info->type) {
1032 sum_addr = S5P_HDMI_AVI_CHECK_SUM;
1033 start_addr = S5P_HDMI_AVI_DATA;
1036 sum_addr = S5P_HDMI_SPD_DATA;
1037 start_addr = S5P_HDMI_SPD_DATA + 4;
1039 writeb((u8)info->type, hdmi_base + S5P_HDMI_SPD_HEADER);
1040 writeb((u8)info->version, hdmi_base + S5P_HDMI_SPD_HEADER + 4);
1041 writeb((u8)info->length, hdmi_base + S5P_HDMI_SPD_HEADER + 8);
1044 sum_addr = S5P_HDMI_AUI_CHECK_SUM;
1045 start_addr = S5P_HDMI_AUI_BYTE1;
1048 sum_addr = S5P_HDMI_MPG_CHECK_SUM;
1049 start_addr = S5P_HDMI_MPG_DATA;
1052 tvout_dbg("undefined infoframe\n");
1056 /* calculate checksum */
1057 sum = (u8)info->type + info->version + info->length;
1058 sum = s5p_hdmi_checksum(sum, info->length, data);
1060 /* write checksum */
1061 writeb(sum, hdmi_base + sum_addr);
1064 hdmi_write_l(data, hdmi_base, start_addr, info->length);
1067 void s5p_hdmi_reg_tg(struct s5p_hdmi_v_frame *frame)
1072 hdmi_write_16(frame->h_total, hdmi_base + S5P_HDMI_TG_H_FSZ_L);
1073 hdmi_write_16(frame->h_blank, hdmi_base + S5P_HDMI_TG_HACT_ST_L);
1074 hdmi_write_16(frame->h_active, hdmi_base + S5P_HDMI_TG_HACT_SZ_L);
1076 hdmi_write_16(frame->v_total, hdmi_base + S5P_HDMI_TG_V_FSZ_L);
1077 hdmi_write_16(frame->v_active, hdmi_base + S5P_HDMI_TG_VACT_SZ_L);
1080 reg = (frame->i_p) ? (frame->v_total - frame->v_active*2) / 2 :
1081 frame->v_total - frame->v_active;
1082 hdmi_write_16(reg, hdmi_base + S5P_HDMI_TG_VACT_ST_L);
1084 reg = (frame->i_p) ? 0x249 : 0x248;
1085 hdmi_write_16(reg, hdmi_base + S5P_HDMI_TG_VACT_ST2_L);
1087 reg = (frame->i_p) ? 0x233 : 1;
1088 hdmi_write_16(reg, hdmi_base + S5P_HDMI_TG_VSYNC_BOT_HDMI_L);
1090 /* write reg default value */
1091 hdmi_write_16(0x1, hdmi_base + S5P_HDMI_TG_VSYNC_L);
1092 hdmi_write_16(0x233, hdmi_base + S5P_HDMI_TG_VSYNC2_L);
1093 hdmi_write_16(0x233, hdmi_base + S5P_HDMI_TG_FIELD_CHG_L);
1094 hdmi_write_16(0x1, hdmi_base + S5P_HDMI_TG_VSYNC_TOP_HDMI_L);
1095 hdmi_write_16(0x1, hdmi_base + S5P_HDMI_TG_FIELD_TOP_HDMI_L);
1096 hdmi_write_16(0x233, hdmi_base + S5P_HDMI_TG_FIELD_BOT_HDMI_L);
1098 tg = readb(hdmi_base + S5P_HDMI_TG_CMD);
1100 hdmi_bit_set(frame->i_p, tg, S5P_HDMI_FIELD);
1102 writeb(tg, hdmi_base + S5P_HDMI_TG_CMD);
1105 void s5p_hdmi_reg_v_timing(struct s5p_hdmi_v_format *v)
1109 struct s5p_hdmi_v_frame *frame = &(v->frame);
1111 writeb(frame->polarity, hdmi_base + S5P_HDMI_SYNC_MODE);
1112 writeb(frame->i_p, hdmi_base + S5P_HDMI_INT_PRO_MODE);
1114 hdmi_write_16(frame->h_blank, hdmi_base + S5P_HDMI_H_BLANK_0);
1116 reg32 = (frame->v_blank << 11) | (frame->v_blank + frame->v_active);
1117 hdmi_write_24(reg32, hdmi_base + S5P_HDMI_V_BLANK_0);
1119 reg32 = (frame->h_total << 12) | frame->v_total;
1120 hdmi_write_24(reg32, hdmi_base + S5P_HDMI_H_V_LINE_0);
1122 reg32 = frame->polarity << 20 | v->h_sync.end << 10 | v->h_sync.begin;
1123 hdmi_write_24(reg32, hdmi_base + S5P_HDMI_H_SYNC_GEN_0);
1125 reg32 = v->v_sync_top.begin << 12 | v->v_sync_top.end;
1126 hdmi_write_24(reg32, hdmi_base + S5P_HDMI_V_SYNC_GEN_1_0);
1129 reg32 = v->v_blank_f.end << 11 | v->v_blank_f.begin;
1130 hdmi_write_24(reg32, hdmi_base + S5P_HDMI_V_BLANK_F_0);
1132 reg32 = v->v_sync_bottom.begin << 12 | v->v_sync_bottom.end;
1133 hdmi_write_24(reg32, hdmi_base + S5P_HDMI_V_SYNC_GEN_2_0);
1135 reg32 = v->v_sync_h_pos.begin << 12 | v->v_sync_h_pos.end;
1136 hdmi_write_24(reg32, hdmi_base + S5P_HDMI_V_SYNC_GEN_3_0);
1138 hdmi_write_24(0x0, hdmi_base + S5P_HDMI_V_BLANK_F_0);
1139 hdmi_write_24(0x1001, hdmi_base + S5P_HDMI_V_SYNC_GEN_2_0);
1140 hdmi_write_24(0x1001, hdmi_base + S5P_HDMI_V_SYNC_GEN_3_0);
1144 void s5p_hdmi_reg_bluescreen_clr(u8 cb_b, u8 y_g, u8 cr_r)
1146 writeb(cb_b, hdmi_base + S5P_HDMI_BLUE_SCREEN_0);
1147 writeb(y_g, hdmi_base + S5P_HDMI_BLUE_SCREEN_1);
1148 writeb(cr_r, hdmi_base + S5P_HDMI_BLUE_SCREEN_2);
1151 void s5p_hdmi_reg_bluescreen(bool en)
1153 u8 reg = readl(hdmi_base + S5P_HDMI_CON_0);
1155 hdmi_bit_set(en, reg, S5P_HDMI_BLUE_SCR_EN);
1157 writeb(reg, hdmi_base + S5P_HDMI_CON_0);
1160 void s5p_hdmi_reg_clr_range(u8 y_min, u8 y_max, u8 c_min, u8 c_max)
1162 writeb(y_max, hdmi_base + S5P_HDMI_YMAX);
1163 writeb(y_min, hdmi_base + S5P_HDMI_YMIN);
1164 writeb(c_max, hdmi_base + S5P_HDMI_CMAX);
1165 writeb(c_min, hdmi_base + S5P_HDMI_CMIN);
1168 void s5p_hdmi_reg_tg_cmd(bool time, bool bt656, bool tg)
1172 reg = readb(hdmi_base + S5P_HDMI_TG_CMD);
1174 hdmi_bit_set(time, reg, S5P_HDMI_GETSYNC_TYPE);
1175 hdmi_bit_set(bt656, reg, S5P_HDMI_GETSYNC);
1176 hdmi_bit_set(tg, reg, S5P_HDMI_TG);
1178 writeb(reg, hdmi_base + S5P_HDMI_TG_CMD);
1181 void s5p_hdmi_reg_enable(bool en)
1185 reg = readl(hdmi_base + S5P_HDMI_CON_0);
1190 reg &= ~(S5P_HDMI_EN | S5P_HDMI_ASP_EN);
1192 writeb(reg, hdmi_base + S5P_HDMI_CON_0);
1195 u8 s5p_hdmi_reg_intc_status(void)
1197 return readb(hdmi_base + S5P_HDMI_INTC_FLAG);
1200 u8 s5p_hdmi_reg_intc_get_enabled(void)
1202 return readb(hdmi_base + S5P_HDMI_INTC_CON);
1205 void s5p_hdmi_reg_intc_clear_pending(enum s5p_hdmi_interrrupt intr)
1209 reg = readb(hdmi_base + S5P_HDMI_INTC_FLAG);
1210 writeb(reg | (1 << intr), hdmi_base + S5P_HDMI_INTC_FLAG);
1214 void s5p_hdmi_reg_sw_hpd_enable(bool enable)
1218 reg = readb(hdmi_base + S5P_HDMI_HPD);
1219 reg &= ~S5P_HDMI_HPD_SEL_I_HPD;
1222 writeb(reg | S5P_HDMI_HPD_SEL_I_HPD, hdmi_base + S5P_HDMI_HPD);
1224 writeb(reg, hdmi_base + S5P_HDMI_HPD);
1227 void s5p_hdmi_reg_set_hpd_onoff(bool on_off)
1231 reg = readb(hdmi_base + S5P_HDMI_HPD);
1232 reg &= ~S5P_HDMI_SW_HPD_PLUGGED;
1235 writel(reg | S5P_HDMI_SW_HPD_PLUGGED,
1236 hdmi_base + S5P_HDMI_HPD);
1238 writel(reg | S5P_HDMI_SW_HPD_UNPLUGGED,
1239 hdmi_base + S5P_HDMI_HPD);
1243 u8 s5p_hdmi_reg_get_hpd_status(void)
1245 return readb(hdmi_base + S5P_HDMI_HPD_STATUS);
1248 void s5p_hdmi_reg_hpd_gen(void)
1250 writeb(0xFF, hdmi_base + S5P_HDMI_HPD_GEN);
1253 int s5p_hdmi_reg_intc_set_isr(irqreturn_t (*isr)(int, void *), u8 num)
1256 tvout_err("invalid irq routine\n");
1260 if (num > HDMI_IRQ_TOTAL_NUM) {
1261 tvout_err("max irq_num exceeded\n");
1265 if (s5p_hdmi_isr_ftn[num])
1266 tvout_dbg("irq %d already registered\n", num);
1268 s5p_hdmi_isr_ftn[num] = isr;
1270 tvout_dbg("success to register irq : %d\n", num);
1275 void s5p_hdmi_reg_intc_enable(enum s5p_hdmi_interrrupt intr, u8 en)
1279 reg = s5p_hdmi_reg_intc_get_enabled();
1283 reg |= S5P_HDMI_INTC_EN_GLOBAL;
1287 reg &= ~(1 << intr);
1290 reg &= ~S5P_HDMI_INTC_EN_GLOBAL;
1293 writeb(reg, hdmi_base + S5P_HDMI_INTC_CON);
1296 void s5p_hdmi_reg_audio_enable(u8 en)
1299 con = readb(hdmi_base + S5P_HDMI_CON_0);
1300 mod = readb(hdmi_base + S5P_HDMI_MODE_SEL);
1303 if (mod & S5P_HDMI_DVI_MODE_EN)
1306 con |= S5P_HDMI_ASP_EN;
1307 writeb(HDMI_TRANS_EVERY_SYNC, hdmi_base + S5P_HDMI_AUI_CON);
1309 con &= ~S5P_HDMI_ASP_EN;
1310 writeb(HDMI_DO_NOT_TANS, hdmi_base + S5P_HDMI_AUI_CON);
1313 writeb(con, hdmi_base + S5P_HDMI_CON_0);
1316 int s5p_hdmi_audio_init(
1317 enum s5p_tvout_audio_codec_type audio_codec,
1318 u32 sample_rate, u32 bits, u32 frame_size_code)
1320 #ifdef CONFIG_SND_S5P_SPDIF
1321 s5p_hdmi_audio_set_config(audio_codec);
1322 s5p_hdmi_audio_set_repetition_time(audio_codec, bits, frame_size_code);
1323 s5p_hdmi_audio_irq_enable(S5P_HDMI_SPDIFIN_IRQ_OVERFLOW_EN);
1324 s5p_hdmi_audio_clock_enable();
1326 s5p_hdmi_audio_i2s_config(audio_codec, sample_rate, bits,
1332 void s5p_hdmi_reg_mute(bool en)
1334 static u8 prev_audio;
1337 s5p_hdmi_reg_bluescreen(en);
1340 reg = readb(hdmi_base + S5P_HDMI_CON_0);
1341 prev_audio = reg & S5P_HDMI_ASP_EN;
1346 s5p_hdmi_reg_audio_enable(!en);
1349 irqreturn_t s5p_hdmi_irq(int irq, void *dev_id)
1353 spin_lock_irq(&lock_hdmi);
1355 state = readb(hdmi_base + S5P_HDMI_INTC_FLAG);
1358 tvout_err("undefined irq : %d\n", state);
1362 for (num = 0; num < HDMI_IRQ_TOTAL_NUM; num++) {
1364 if (!(state & (1 << num)))
1367 if (s5p_hdmi_isr_ftn[num])
1368 (s5p_hdmi_isr_ftn[num])(num, NULL);
1370 tvout_dbg("unregistered irq : %d\n", num);
1374 spin_unlock_irq(&lock_hdmi);
1379 void s5p_hdmi_init(void __iomem *hdmi_addr, void __iomem *hdmi_phy_addr)
1381 hdmi_base = hdmi_addr;
1382 i2c_hdmi_phy_base = hdmi_phy_addr;
1384 spin_lock_init(&lock_hdmi);
1386 writeb(0x5, i2c_hdmi_phy_base + HDMI_I2C_LC);
1389 void s5p_hdmi_reg_output(struct s5p_hdmi_o_reg *reg)
1391 writeb(reg->pxl_limit, hdmi_base + S5P_HDMI_CON_1);
1392 writeb(reg->preemble, hdmi_base + S5P_HDMI_CON_2);
1393 writeb(reg->mode, hdmi_base + S5P_HDMI_MODE_SEL);
1396 void s5p_hdmi_reg_packet_trans(struct s5p_hdmi_o_trans *trans)
1400 writeb(trans->avi, hdmi_base + S5P_HDMI_AVI_CON);
1401 writeb(trans->mpg, hdmi_base + S5P_HDMI_MPG_CON);
1402 writeb(trans->spd, hdmi_base + S5P_HDMI_SPD_CON);
1403 writeb(trans->gmp, hdmi_base + S5P_HDMI_GAMUT_CON);
1404 writeb(trans->aui, hdmi_base + S5P_HDMI_AUI_CON);
1406 reg = trans->gcp | readb(hdmi_base + S5P_HDMI_GCP_CON);
1407 writeb(reg, hdmi_base + S5P_HDMI_GCP_CON);
1409 reg = trans->isrc | readb(hdmi_base + S5P_HDMI_ISRC_CON);
1410 writeb(reg, hdmi_base + S5P_HDMI_ISRC_CON);
1412 reg = trans->acp | readb(hdmi_base + S5P_HDMI_ACP_CON);
1413 writeb(reg, hdmi_base + S5P_HDMI_ACP_CON);
1415 reg = trans->acr | readb(hdmi_base + S5P_HDMI_ACP_CON);
1416 writeb(reg, hdmi_base + S5P_HDMI_ACR_CON);