1
2
3
4
5
6
7
8
9
10
11
12
13
14#ifdef CONFIG_VIDEO_SAMSUNG_S5P_HDMI_DEBUG
15#define DEBUG
16#endif
17
18#include <linux/kernel.h>
19#include <linux/slab.h>
20#include <linux/io.h>
21#include <linux/i2c.h>
22#include <linux/platform_device.h>
23#include <media/v4l2-subdev.h>
24#include <linux/module.h>
25#include <linux/interrupt.h>
26#include <linux/irq.h>
27#include <linux/delay.h>
28#include <linux/bug.h>
29#include <linux/pm_runtime.h>
30#include <linux/clk.h>
31#include <linux/regulator/consumer.h>
32
33#include <media/s5p_hdmi.h>
34#include <media/v4l2-common.h>
35#include <media/v4l2-dev.h>
36#include <media/v4l2-device.h>
37
38#include "regs-hdmi.h"
39
40MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
41MODULE_DESCRIPTION("Samsung HDMI");
42MODULE_LICENSE("GPL");
43
44
45#define HDMI_DEFAULT_PRESET V4L2_DV_1080P60
46
47struct hdmi_resources {
48 struct clk *hdmi;
49 struct clk *sclk_hdmi;
50 struct clk *sclk_pixel;
51 struct clk *sclk_hdmiphy;
52 struct clk *hdmiphy;
53 struct regulator_bulk_data *regul_bulk;
54 int regul_count;
55};
56
57struct hdmi_device {
58
59 void __iomem *regs;
60
61 unsigned int irq;
62
63 struct device *dev;
64
65 struct v4l2_subdev sd;
66
67 struct v4l2_device v4l2_dev;
68
69 struct v4l2_subdev *phy_sd;
70
71 struct v4l2_subdev *mhl_sd;
72
73 const struct hdmi_preset_conf *cur_conf;
74
75 u32 cur_preset;
76
77 struct hdmi_resources res;
78};
79
80struct hdmi_tg_regs {
81 u8 cmd;
82 u8 h_fsz_l;
83 u8 h_fsz_h;
84 u8 hact_st_l;
85 u8 hact_st_h;
86 u8 hact_sz_l;
87 u8 hact_sz_h;
88 u8 v_fsz_l;
89 u8 v_fsz_h;
90 u8 vsync_l;
91 u8 vsync_h;
92 u8 vsync2_l;
93 u8 vsync2_h;
94 u8 vact_st_l;
95 u8 vact_st_h;
96 u8 vact_sz_l;
97 u8 vact_sz_h;
98 u8 field_chg_l;
99 u8 field_chg_h;
100 u8 vact_st2_l;
101 u8 vact_st2_h;
102 u8 vsync_top_hdmi_l;
103 u8 vsync_top_hdmi_h;
104 u8 vsync_bot_hdmi_l;
105 u8 vsync_bot_hdmi_h;
106 u8 field_top_hdmi_l;
107 u8 field_top_hdmi_h;
108 u8 field_bot_hdmi_l;
109 u8 field_bot_hdmi_h;
110};
111
112struct hdmi_core_regs {
113 u8 h_blank[2];
114 u8 v_blank[3];
115 u8 h_v_line[3];
116 u8 vsync_pol[1];
117 u8 int_pro_mode[1];
118 u8 v_blank_f[3];
119 u8 h_sync_gen[3];
120 u8 v_sync_gen1[3];
121 u8 v_sync_gen2[3];
122 u8 v_sync_gen3[3];
123};
124
125struct hdmi_preset_conf {
126 struct hdmi_core_regs core;
127 struct hdmi_tg_regs tg;
128 struct v4l2_mbus_framefmt mbus_fmt;
129};
130
131static struct platform_device_id hdmi_driver_types[] = {
132 {
133 .name = "s5pv210-hdmi",
134 }, {
135 .name = "exynos4-hdmi",
136 }, {
137
138 }
139};
140
141static const struct v4l2_subdev_ops hdmi_sd_ops;
142
143static struct hdmi_device *sd_to_hdmi_dev(struct v4l2_subdev *sd)
144{
145 return container_of(sd, struct hdmi_device, sd);
146}
147
148static inline
149void hdmi_write(struct hdmi_device *hdev, u32 reg_id, u32 value)
150{
151 writel(value, hdev->regs + reg_id);
152}
153
154static inline
155void hdmi_write_mask(struct hdmi_device *hdev, u32 reg_id, u32 value, u32 mask)
156{
157 u32 old = readl(hdev->regs + reg_id);
158 value = (value & mask) | (old & ~mask);
159 writel(value, hdev->regs + reg_id);
160}
161
162static inline
163void hdmi_writeb(struct hdmi_device *hdev, u32 reg_id, u8 value)
164{
165 writeb(value, hdev->regs + reg_id);
166}
167
168static inline u32 hdmi_read(struct hdmi_device *hdev, u32 reg_id)
169{
170 return readl(hdev->regs + reg_id);
171}
172
173static irqreturn_t hdmi_irq_handler(int irq, void *dev_data)
174{
175 struct hdmi_device *hdev = dev_data;
176 u32 intc_flag;
177
178 (void)irq;
179 intc_flag = hdmi_read(hdev, HDMI_INTC_FLAG);
180
181 if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
182 printk(KERN_INFO "unplugged\n");
183 hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
184 HDMI_INTC_FLAG_HPD_UNPLUG);
185 }
186 if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
187 printk(KERN_INFO "plugged\n");
188 hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
189 HDMI_INTC_FLAG_HPD_PLUG);
190 }
191
192 return IRQ_HANDLED;
193}
194
195static void hdmi_reg_init(struct hdmi_device *hdev)
196{
197
198 hdmi_write_mask(hdev, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
199 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
200
201 hdmi_write_mask(hdev, HDMI_MODE_SEL,
202 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
203 hdmi_write_mask(hdev, HDMI_CON_2, ~0,
204 HDMI_DVI_PERAMBLE_EN | HDMI_DVI_BAND_EN);
205
206 hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
207
208 hdmi_writeb(hdev, HDMI_BLUE_SCREEN_0, 0x12);
209 hdmi_writeb(hdev, HDMI_BLUE_SCREEN_1, 0x34);
210 hdmi_writeb(hdev, HDMI_BLUE_SCREEN_2, 0x56);
211}
212
213static void hdmi_timing_apply(struct hdmi_device *hdev,
214 const struct hdmi_preset_conf *conf)
215{
216 const struct hdmi_core_regs *core = &conf->core;
217 const struct hdmi_tg_regs *tg = &conf->tg;
218
219
220 hdmi_writeb(hdev, HDMI_H_BLANK_0, core->h_blank[0]);
221 hdmi_writeb(hdev, HDMI_H_BLANK_1, core->h_blank[1]);
222 hdmi_writeb(hdev, HDMI_V_BLANK_0, core->v_blank[0]);
223 hdmi_writeb(hdev, HDMI_V_BLANK_1, core->v_blank[1]);
224 hdmi_writeb(hdev, HDMI_V_BLANK_2, core->v_blank[2]);
225 hdmi_writeb(hdev, HDMI_H_V_LINE_0, core->h_v_line[0]);
226 hdmi_writeb(hdev, HDMI_H_V_LINE_1, core->h_v_line[1]);
227 hdmi_writeb(hdev, HDMI_H_V_LINE_2, core->h_v_line[2]);
228 hdmi_writeb(hdev, HDMI_VSYNC_POL, core->vsync_pol[0]);
229 hdmi_writeb(hdev, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
230 hdmi_writeb(hdev, HDMI_V_BLANK_F_0, core->v_blank_f[0]);
231 hdmi_writeb(hdev, HDMI_V_BLANK_F_1, core->v_blank_f[1]);
232 hdmi_writeb(hdev, HDMI_V_BLANK_F_2, core->v_blank_f[2]);
233 hdmi_writeb(hdev, HDMI_H_SYNC_GEN_0, core->h_sync_gen[0]);
234 hdmi_writeb(hdev, HDMI_H_SYNC_GEN_1, core->h_sync_gen[1]);
235 hdmi_writeb(hdev, HDMI_H_SYNC_GEN_2, core->h_sync_gen[2]);
236 hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
237 hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
238 hdmi_writeb(hdev, HDMI_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
239 hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
240 hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
241 hdmi_writeb(hdev, HDMI_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
242 hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
243 hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
244 hdmi_writeb(hdev, HDMI_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
245
246 hdmi_writeb(hdev, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
247 hdmi_writeb(hdev, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
248 hdmi_writeb(hdev, HDMI_TG_HACT_ST_L, tg->hact_st_l);
249 hdmi_writeb(hdev, HDMI_TG_HACT_ST_H, tg->hact_st_h);
250 hdmi_writeb(hdev, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
251 hdmi_writeb(hdev, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
252 hdmi_writeb(hdev, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
253 hdmi_writeb(hdev, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
254 hdmi_writeb(hdev, HDMI_TG_VSYNC_L, tg->vsync_l);
255 hdmi_writeb(hdev, HDMI_TG_VSYNC_H, tg->vsync_h);
256 hdmi_writeb(hdev, HDMI_TG_VSYNC2_L, tg->vsync2_l);
257 hdmi_writeb(hdev, HDMI_TG_VSYNC2_H, tg->vsync2_h);
258 hdmi_writeb(hdev, HDMI_TG_VACT_ST_L, tg->vact_st_l);
259 hdmi_writeb(hdev, HDMI_TG_VACT_ST_H, tg->vact_st_h);
260 hdmi_writeb(hdev, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
261 hdmi_writeb(hdev, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
262 hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
263 hdmi_writeb(hdev, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
264 hdmi_writeb(hdev, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
265 hdmi_writeb(hdev, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
266 hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
267 hdmi_writeb(hdev, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
268 hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
269 hdmi_writeb(hdev, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
270 hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
271 hdmi_writeb(hdev, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
272 hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
273 hdmi_writeb(hdev, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
274}
275
276static int hdmi_conf_apply(struct hdmi_device *hdmi_dev)
277{
278 struct device *dev = hdmi_dev->dev;
279 const struct hdmi_preset_conf *conf = hdmi_dev->cur_conf;
280 struct v4l2_dv_preset preset;
281 int ret;
282
283 dev_dbg(dev, "%s\n", __func__);
284
285
286 hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT, ~0, HDMI_PHY_SW_RSTOUT);
287 mdelay(10);
288 hdmi_write_mask(hdmi_dev, HDMI_PHY_RSTOUT, 0, HDMI_PHY_SW_RSTOUT);
289 mdelay(10);
290
291
292 preset.preset = hdmi_dev->cur_preset;
293 ret = v4l2_subdev_call(hdmi_dev->phy_sd, video, s_dv_preset, &preset);
294 if (ret) {
295 dev_err(dev, "failed to set preset (%u)\n", preset.preset);
296 return ret;
297 }
298
299
300 hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT, 0, HDMI_CORE_SW_RSTOUT);
301 mdelay(10);
302 hdmi_write_mask(hdmi_dev, HDMI_CORE_RSTOUT, ~0, HDMI_CORE_SW_RSTOUT);
303 mdelay(10);
304
305 hdmi_reg_init(hdmi_dev);
306
307
308 hdmi_timing_apply(hdmi_dev, conf);
309
310 return 0;
311}
312
313static void hdmi_dumpregs(struct hdmi_device *hdev, char *prefix)
314{
315#define DUMPREG(reg_id) \
316 dev_dbg(hdev->dev, "%s:" #reg_id " = %08x\n", prefix, \
317 readl(hdev->regs + reg_id))
318
319 dev_dbg(hdev->dev, "%s: ---- CONTROL REGISTERS ----\n", prefix);
320 DUMPREG(HDMI_INTC_FLAG);
321 DUMPREG(HDMI_INTC_CON);
322 DUMPREG(HDMI_HPD_STATUS);
323 DUMPREG(HDMI_PHY_RSTOUT);
324 DUMPREG(HDMI_PHY_VPLL);
325 DUMPREG(HDMI_PHY_CMU);
326 DUMPREG(HDMI_CORE_RSTOUT);
327
328 dev_dbg(hdev->dev, "%s: ---- CORE REGISTERS ----\n", prefix);
329 DUMPREG(HDMI_CON_0);
330 DUMPREG(HDMI_CON_1);
331 DUMPREG(HDMI_CON_2);
332 DUMPREG(HDMI_SYS_STATUS);
333 DUMPREG(HDMI_PHY_STATUS);
334 DUMPREG(HDMI_STATUS_EN);
335 DUMPREG(HDMI_HPD);
336 DUMPREG(HDMI_MODE_SEL);
337 DUMPREG(HDMI_HPD_GEN);
338 DUMPREG(HDMI_DC_CONTROL);
339 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
340
341 dev_dbg(hdev->dev, "%s: ---- CORE SYNC REGISTERS ----\n", prefix);
342 DUMPREG(HDMI_H_BLANK_0);
343 DUMPREG(HDMI_H_BLANK_1);
344 DUMPREG(HDMI_V_BLANK_0);
345 DUMPREG(HDMI_V_BLANK_1);
346 DUMPREG(HDMI_V_BLANK_2);
347 DUMPREG(HDMI_H_V_LINE_0);
348 DUMPREG(HDMI_H_V_LINE_1);
349 DUMPREG(HDMI_H_V_LINE_2);
350 DUMPREG(HDMI_VSYNC_POL);
351 DUMPREG(HDMI_INT_PRO_MODE);
352 DUMPREG(HDMI_V_BLANK_F_0);
353 DUMPREG(HDMI_V_BLANK_F_1);
354 DUMPREG(HDMI_V_BLANK_F_2);
355 DUMPREG(HDMI_H_SYNC_GEN_0);
356 DUMPREG(HDMI_H_SYNC_GEN_1);
357 DUMPREG(HDMI_H_SYNC_GEN_2);
358 DUMPREG(HDMI_V_SYNC_GEN_1_0);
359 DUMPREG(HDMI_V_SYNC_GEN_1_1);
360 DUMPREG(HDMI_V_SYNC_GEN_1_2);
361 DUMPREG(HDMI_V_SYNC_GEN_2_0);
362 DUMPREG(HDMI_V_SYNC_GEN_2_1);
363 DUMPREG(HDMI_V_SYNC_GEN_2_2);
364 DUMPREG(HDMI_V_SYNC_GEN_3_0);
365 DUMPREG(HDMI_V_SYNC_GEN_3_1);
366 DUMPREG(HDMI_V_SYNC_GEN_3_2);
367
368 dev_dbg(hdev->dev, "%s: ---- TG REGISTERS ----\n", prefix);
369 DUMPREG(HDMI_TG_CMD);
370 DUMPREG(HDMI_TG_H_FSZ_L);
371 DUMPREG(HDMI_TG_H_FSZ_H);
372 DUMPREG(HDMI_TG_HACT_ST_L);
373 DUMPREG(HDMI_TG_HACT_ST_H);
374 DUMPREG(HDMI_TG_HACT_SZ_L);
375 DUMPREG(HDMI_TG_HACT_SZ_H);
376 DUMPREG(HDMI_TG_V_FSZ_L);
377 DUMPREG(HDMI_TG_V_FSZ_H);
378 DUMPREG(HDMI_TG_VSYNC_L);
379 DUMPREG(HDMI_TG_VSYNC_H);
380 DUMPREG(HDMI_TG_VSYNC2_L);
381 DUMPREG(HDMI_TG_VSYNC2_H);
382 DUMPREG(HDMI_TG_VACT_ST_L);
383 DUMPREG(HDMI_TG_VACT_ST_H);
384 DUMPREG(HDMI_TG_VACT_SZ_L);
385 DUMPREG(HDMI_TG_VACT_SZ_H);
386 DUMPREG(HDMI_TG_FIELD_CHG_L);
387 DUMPREG(HDMI_TG_FIELD_CHG_H);
388 DUMPREG(HDMI_TG_VACT_ST2_L);
389 DUMPREG(HDMI_TG_VACT_ST2_H);
390 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
391 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
392 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
393 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
394 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
395 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
396 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
397 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
398#undef DUMPREG
399}
400
401static const struct hdmi_preset_conf hdmi_conf_480p = {
402 .core = {
403 .h_blank = {0x8a, 0x00},
404 .v_blank = {0x0d, 0x6a, 0x01},
405 .h_v_line = {0x0d, 0xa2, 0x35},
406 .vsync_pol = {0x01},
407 .int_pro_mode = {0x00},
408 .v_blank_f = {0x00, 0x00, 0x00},
409 .h_sync_gen = {0x0e, 0x30, 0x11},
410 .v_sync_gen1 = {0x0f, 0x90, 0x00},
411
412 },
413 .tg = {
414 0x00,
415 0x5a, 0x03,
416 0x8a, 0x00, 0xd0, 0x02,
417 0x0d, 0x02,
418 0x01, 0x00, 0x33, 0x02,
419 0x2d, 0x00, 0xe0, 0x01,
420 0x33, 0x02,
421 0x49, 0x02,
422 0x01, 0x00, 0x33, 0x02,
423 0x01, 0x00, 0x33, 0x02,
424 },
425 .mbus_fmt = {
426 .width = 720,
427 .height = 480,
428 .code = V4L2_MBUS_FMT_FIXED,
429 .field = V4L2_FIELD_NONE,
430 .colorspace = V4L2_COLORSPACE_SRGB,
431 },
432};
433
434static const struct hdmi_preset_conf hdmi_conf_720p60 = {
435 .core = {
436 .h_blank = {0x72, 0x01},
437 .v_blank = {0xee, 0xf2, 0x00},
438 .h_v_line = {0xee, 0x22, 0x67},
439 .vsync_pol = {0x00},
440 .int_pro_mode = {0x00},
441 .v_blank_f = {0x00, 0x00, 0x00},
442 .h_sync_gen = {0x6c, 0x50, 0x02},
443 .v_sync_gen1 = {0x0a, 0x50, 0x00},
444
445 },
446 .tg = {
447 0x00,
448 0x72, 0x06,
449 0x72, 0x01, 0x00, 0x05,
450 0xee, 0x02,
451 0x01, 0x00, 0x33, 0x02,
452 0x1e, 0x00, 0xd0, 0x02,
453 0x33, 0x02,
454 0x49, 0x02,
455 0x01, 0x00, 0x33, 0x02,
456 0x01, 0x00, 0x33, 0x02,
457 },
458 .mbus_fmt = {
459 .width = 1280,
460 .height = 720,
461 .code = V4L2_MBUS_FMT_FIXED,
462 .field = V4L2_FIELD_NONE,
463 .colorspace = V4L2_COLORSPACE_SRGB,
464 },
465};
466
467static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
468 .core = {
469 .h_blank = {0xd0, 0x02},
470 .v_blank = {0x65, 0x6c, 0x01},
471 .h_v_line = {0x65, 0x04, 0xa5},
472 .vsync_pol = {0x00},
473 .int_pro_mode = {0x00},
474 .v_blank_f = {0x00, 0x00, 0x00},
475 .h_sync_gen = {0x0e, 0xea, 0x08},
476 .v_sync_gen1 = {0x09, 0x40, 0x00},
477
478 },
479 .tg = {
480 0x00,
481 0x98, 0x08,
482 0x18, 0x01, 0x80, 0x07,
483 0x65, 0x04,
484 0x01, 0x00, 0x33, 0x02,
485 0x2d, 0x00, 0x38, 0x04,
486 0x33, 0x02,
487 0x49, 0x02,
488 0x01, 0x00, 0x33, 0x02,
489 0x01, 0x00, 0x33, 0x02,
490 },
491 .mbus_fmt = {
492 .width = 1920,
493 .height = 1080,
494 .code = V4L2_MBUS_FMT_FIXED,
495 .field = V4L2_FIELD_NONE,
496 .colorspace = V4L2_COLORSPACE_SRGB,
497 },
498};
499
500static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
501 .core = {
502 .h_blank = {0x18, 0x01},
503 .v_blank = {0x65, 0x6c, 0x01},
504 .h_v_line = {0x65, 0x84, 0x89},
505 .vsync_pol = {0x00},
506 .int_pro_mode = {0x00},
507 .v_blank_f = {0x00, 0x00, 0x00},
508 .h_sync_gen = {0x56, 0x08, 0x02},
509 .v_sync_gen1 = {0x09, 0x40, 0x00},
510
511 },
512 .tg = {
513 0x00,
514 0x98, 0x08,
515 0x18, 0x01, 0x80, 0x07,
516 0x65, 0x04,
517 0x01, 0x00, 0x33, 0x02,
518 0x2d, 0x00, 0x38, 0x04,
519 0x33, 0x02,
520 0x48, 0x02,
521 0x01, 0x00, 0x01, 0x00,
522 0x01, 0x00, 0x33, 0x02,
523 },
524 .mbus_fmt = {
525 .width = 1920,
526 .height = 1080,
527 .code = V4L2_MBUS_FMT_FIXED,
528 .field = V4L2_FIELD_NONE,
529 .colorspace = V4L2_COLORSPACE_SRGB,
530 },
531};
532
533static const struct {
534 u32 preset;
535 const struct hdmi_preset_conf *conf;
536} hdmi_conf[] = {
537 { V4L2_DV_480P59_94, &hdmi_conf_480p },
538 { V4L2_DV_720P59_94, &hdmi_conf_720p60 },
539 { V4L2_DV_1080P50, &hdmi_conf_1080p50 },
540 { V4L2_DV_1080P30, &hdmi_conf_1080p60 },
541 { V4L2_DV_1080P60, &hdmi_conf_1080p60 },
542};
543
544static const struct hdmi_preset_conf *hdmi_preset2conf(u32 preset)
545{
546 int i;
547
548 for (i = 0; i < ARRAY_SIZE(hdmi_conf); ++i)
549 if (hdmi_conf[i].preset == preset)
550 return hdmi_conf[i].conf;
551 return NULL;
552}
553
554static int hdmi_streamon(struct hdmi_device *hdev)
555{
556 struct device *dev = hdev->dev;
557 struct hdmi_resources *res = &hdev->res;
558 int ret, tries;
559
560 dev_dbg(dev, "%s\n", __func__);
561
562 ret = v4l2_subdev_call(hdev->phy_sd, video, s_stream, 1);
563 if (ret)
564 return ret;
565
566
567 for (tries = 100; tries; --tries) {
568 u32 val = hdmi_read(hdev, HDMI_PHY_STATUS);
569 if (val & HDMI_PHY_STATUS_READY)
570 break;
571 mdelay(1);
572 }
573
574 if (tries == 0) {
575 dev_err(dev, "hdmiphy's pll could not reach steady state.\n");
576 v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0);
577 hdmi_dumpregs(hdev, "hdmiphy - s_stream");
578 return -EIO;
579 }
580
581
582 ret = v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 1);
583 if (hdev->mhl_sd && ret) {
584 v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0);
585 hdmi_dumpregs(hdev, "mhl - s_stream");
586 return -EIO;
587 }
588
589
590 clk_disable(res->sclk_hdmi);
591 clk_set_parent(res->sclk_hdmi, res->sclk_hdmiphy);
592 clk_enable(res->sclk_hdmi);
593
594
595 hdmi_write_mask(hdev, HDMI_CON_0, ~0, HDMI_EN);
596 hdmi_write_mask(hdev, HDMI_TG_CMD, ~0, HDMI_TG_EN);
597 hdmi_dumpregs(hdev, "streamon");
598 return 0;
599}
600
601static int hdmi_streamoff(struct hdmi_device *hdev)
602{
603 struct device *dev = hdev->dev;
604 struct hdmi_resources *res = &hdev->res;
605
606 dev_dbg(dev, "%s\n", __func__);
607
608 hdmi_write_mask(hdev, HDMI_CON_0, 0, HDMI_EN);
609 hdmi_write_mask(hdev, HDMI_TG_CMD, 0, HDMI_TG_EN);
610
611
612 clk_disable(res->sclk_hdmi);
613 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
614 clk_enable(res->sclk_hdmi);
615
616 v4l2_subdev_call(hdev->mhl_sd, video, s_stream, 0);
617 v4l2_subdev_call(hdev->phy_sd, video, s_stream, 0);
618
619 hdmi_dumpregs(hdev, "streamoff");
620 return 0;
621}
622
623static int hdmi_s_stream(struct v4l2_subdev *sd, int enable)
624{
625 struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
626 struct device *dev = hdev->dev;
627
628 dev_dbg(dev, "%s(%d)\n", __func__, enable);
629 if (enable)
630 return hdmi_streamon(hdev);
631 return hdmi_streamoff(hdev);
632}
633
634static void hdmi_resource_poweron(struct hdmi_resources *res)
635{
636
637 regulator_bulk_enable(res->regul_count, res->regul_bulk);
638
639 clk_enable(res->hdmiphy);
640
641 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
642
643 clk_enable(res->sclk_hdmi);
644}
645
646static void hdmi_resource_poweroff(struct hdmi_resources *res)
647{
648
649 clk_disable(res->sclk_hdmi);
650
651 clk_disable(res->hdmiphy);
652
653 regulator_bulk_disable(res->regul_count, res->regul_bulk);
654}
655
656static int hdmi_s_power(struct v4l2_subdev *sd, int on)
657{
658 struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
659 int ret;
660
661 if (on)
662 ret = pm_runtime_get_sync(hdev->dev);
663 else
664 ret = pm_runtime_put_sync(hdev->dev);
665
666 return IS_ERR_VALUE(ret) ? ret : 0;
667}
668
669static int hdmi_s_dv_preset(struct v4l2_subdev *sd,
670 struct v4l2_dv_preset *preset)
671{
672 struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
673 struct device *dev = hdev->dev;
674 const struct hdmi_preset_conf *conf;
675
676 conf = hdmi_preset2conf(preset->preset);
677 if (conf == NULL) {
678 dev_err(dev, "preset (%u) not supported\n", preset->preset);
679 return -EINVAL;
680 }
681 hdev->cur_conf = conf;
682 hdev->cur_preset = preset->preset;
683 return 0;
684}
685
686static int hdmi_g_dv_preset(struct v4l2_subdev *sd,
687 struct v4l2_dv_preset *preset)
688{
689 memset(preset, 0, sizeof(*preset));
690 preset->preset = sd_to_hdmi_dev(sd)->cur_preset;
691 return 0;
692}
693
694static int hdmi_g_mbus_fmt(struct v4l2_subdev *sd,
695 struct v4l2_mbus_framefmt *fmt)
696{
697 struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
698 struct device *dev = hdev->dev;
699
700 dev_dbg(dev, "%s\n", __func__);
701 if (!hdev->cur_conf)
702 return -EINVAL;
703 *fmt = hdev->cur_conf->mbus_fmt;
704 return 0;
705}
706
707static int hdmi_enum_dv_presets(struct v4l2_subdev *sd,
708 struct v4l2_dv_enum_preset *preset)
709{
710 if (preset->index >= ARRAY_SIZE(hdmi_conf))
711 return -EINVAL;
712 return v4l_fill_dv_preset_info(hdmi_conf[preset->index].preset, preset);
713}
714
715static const struct v4l2_subdev_core_ops hdmi_sd_core_ops = {
716 .s_power = hdmi_s_power,
717};
718
719static const struct v4l2_subdev_video_ops hdmi_sd_video_ops = {
720 .s_dv_preset = hdmi_s_dv_preset,
721 .g_dv_preset = hdmi_g_dv_preset,
722 .enum_dv_presets = hdmi_enum_dv_presets,
723 .g_mbus_fmt = hdmi_g_mbus_fmt,
724 .s_stream = hdmi_s_stream,
725};
726
727static const struct v4l2_subdev_ops hdmi_sd_ops = {
728 .core = &hdmi_sd_core_ops,
729 .video = &hdmi_sd_video_ops,
730};
731
732static int hdmi_runtime_suspend(struct device *dev)
733{
734 struct v4l2_subdev *sd = dev_get_drvdata(dev);
735 struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
736
737 dev_dbg(dev, "%s\n", __func__);
738 v4l2_subdev_call(hdev->mhl_sd, core, s_power, 0);
739 hdmi_resource_poweroff(&hdev->res);
740 return 0;
741}
742
743static int hdmi_runtime_resume(struct device *dev)
744{
745 struct v4l2_subdev *sd = dev_get_drvdata(dev);
746 struct hdmi_device *hdev = sd_to_hdmi_dev(sd);
747 int ret = 0;
748
749 dev_dbg(dev, "%s\n", __func__);
750
751 hdmi_resource_poweron(&hdev->res);
752
753 ret = hdmi_conf_apply(hdev);
754 if (ret)
755 goto fail;
756
757
758 ret = v4l2_subdev_call(hdev->mhl_sd, core, s_power, 1);
759 if (hdev->mhl_sd && ret)
760 goto fail;
761
762 dev_dbg(dev, "poweron succeed\n");
763
764 return 0;
765
766fail:
767 hdmi_resource_poweroff(&hdev->res);
768 dev_err(dev, "poweron failed\n");
769
770 return ret;
771}
772
773static const struct dev_pm_ops hdmi_pm_ops = {
774 .runtime_suspend = hdmi_runtime_suspend,
775 .runtime_resume = hdmi_runtime_resume,
776};
777
778static void hdmi_resources_cleanup(struct hdmi_device *hdev)
779{
780 struct hdmi_resources *res = &hdev->res;
781
782 dev_dbg(hdev->dev, "HDMI resource cleanup\n");
783
784 if (res->regul_count)
785 regulator_bulk_free(res->regul_count, res->regul_bulk);
786
787 kfree(res->regul_bulk);
788 if (!IS_ERR_OR_NULL(res->hdmiphy))
789 clk_put(res->hdmiphy);
790 if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
791 clk_put(res->sclk_hdmiphy);
792 if (!IS_ERR_OR_NULL(res->sclk_pixel))
793 clk_put(res->sclk_pixel);
794 if (!IS_ERR_OR_NULL(res->sclk_hdmi))
795 clk_put(res->sclk_hdmi);
796 if (!IS_ERR_OR_NULL(res->hdmi))
797 clk_put(res->hdmi);
798 memset(res, 0, sizeof *res);
799}
800
801static int hdmi_resources_init(struct hdmi_device *hdev)
802{
803 struct device *dev = hdev->dev;
804 struct hdmi_resources *res = &hdev->res;
805 static char *supply[] = {
806 "hdmi-en",
807 "vdd",
808 "vdd_osc",
809 "vdd_pll",
810 };
811 int i, ret;
812
813 dev_dbg(dev, "HDMI resource init\n");
814
815 memset(res, 0, sizeof *res);
816
817
818 res->hdmi = clk_get(dev, "hdmi");
819 if (IS_ERR_OR_NULL(res->hdmi)) {
820 dev_err(dev, "failed to get clock 'hdmi'\n");
821 goto fail;
822 }
823 res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
824 if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
825 dev_err(dev, "failed to get clock 'sclk_hdmi'\n");
826 goto fail;
827 }
828 res->sclk_pixel = clk_get(dev, "sclk_pixel");
829 if (IS_ERR_OR_NULL(res->sclk_pixel)) {
830 dev_err(dev, "failed to get clock 'sclk_pixel'\n");
831 goto fail;
832 }
833 res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
834 if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
835 dev_err(dev, "failed to get clock 'sclk_hdmiphy'\n");
836 goto fail;
837 }
838 res->hdmiphy = clk_get(dev, "hdmiphy");
839 if (IS_ERR_OR_NULL(res->hdmiphy)) {
840 dev_err(dev, "failed to get clock 'hdmiphy'\n");
841 goto fail;
842 }
843 res->regul_bulk = kcalloc(ARRAY_SIZE(supply),
844 sizeof(res->regul_bulk[0]), GFP_KERNEL);
845 if (!res->regul_bulk) {
846 dev_err(dev, "failed to get memory for regulators\n");
847 goto fail;
848 }
849 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
850 res->regul_bulk[i].supply = supply[i];
851 res->regul_bulk[i].consumer = NULL;
852 }
853
854 ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
855 if (ret) {
856 dev_err(dev, "failed to get regulators\n");
857 goto fail;
858 }
859 res->regul_count = ARRAY_SIZE(supply);
860
861 return 0;
862fail:
863 dev_err(dev, "HDMI resource init - failed\n");
864 hdmi_resources_cleanup(hdev);
865 return -ENODEV;
866}
867
868static int __devinit hdmi_probe(struct platform_device *pdev)
869{
870 struct device *dev = &pdev->dev;
871 struct resource *res;
872 struct i2c_adapter *adapter;
873 struct v4l2_subdev *sd;
874 struct hdmi_device *hdmi_dev = NULL;
875 struct s5p_hdmi_platform_data *pdata = dev->platform_data;
876 int ret;
877
878 dev_dbg(dev, "probe start\n");
879
880 if (!pdata) {
881 dev_err(dev, "platform data is missing\n");
882 ret = -ENODEV;
883 goto fail;
884 }
885
886 hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(*hdmi_dev), GFP_KERNEL);
887 if (!hdmi_dev) {
888 dev_err(dev, "out of memory\n");
889 ret = -ENOMEM;
890 goto fail;
891 }
892
893 hdmi_dev->dev = dev;
894
895 ret = hdmi_resources_init(hdmi_dev);
896 if (ret)
897 goto fail;
898
899
900 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
901 if (res == NULL) {
902 dev_err(dev, "get memory resource failed.\n");
903 ret = -ENXIO;
904 goto fail_init;
905 }
906
907 hdmi_dev->regs = devm_ioremap(&pdev->dev, res->start,
908 resource_size(res));
909 if (hdmi_dev->regs == NULL) {
910 dev_err(dev, "register mapping failed.\n");
911 ret = -ENXIO;
912 goto fail_init;
913 }
914
915 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
916 if (res == NULL) {
917 dev_err(dev, "get interrupt resource failed.\n");
918 ret = -ENXIO;
919 goto fail_init;
920 }
921
922 ret = devm_request_irq(&pdev->dev, res->start, hdmi_irq_handler, 0,
923 "hdmi", hdmi_dev);
924 if (ret) {
925 dev_err(dev, "request interrupt failed.\n");
926 goto fail_init;
927 }
928 hdmi_dev->irq = res->start;
929
930
931 strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
932 sizeof(hdmi_dev->v4l2_dev.name));
933
934 ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
935 if (ret) {
936 dev_err(dev, "could not register v4l2 device.\n");
937 goto fail_init;
938 }
939
940
941 if (!pdata->hdmiphy_info) {
942 dev_err(dev, "hdmiphy info is missing in platform data\n");
943 ret = -ENXIO;
944 goto fail_vdev;
945 }
946
947 adapter = i2c_get_adapter(pdata->hdmiphy_bus);
948 if (adapter == NULL) {
949 dev_err(dev, "hdmiphy adapter request failed\n");
950 ret = -ENXIO;
951 goto fail_vdev;
952 }
953
954 hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
955 adapter, pdata->hdmiphy_info, NULL);
956
957 i2c_put_adapter(adapter);
958 if (hdmi_dev->phy_sd == NULL) {
959 dev_err(dev, "missing subdev for hdmiphy\n");
960 ret = -ENODEV;
961 goto fail_vdev;
962 }
963
964
965 if (pdata->mhl_info) {
966 adapter = i2c_get_adapter(pdata->mhl_bus);
967 if (adapter == NULL) {
968 dev_err(dev, "MHL adapter request failed\n");
969 ret = -ENXIO;
970 goto fail_vdev;
971 }
972
973 hdmi_dev->mhl_sd = v4l2_i2c_new_subdev_board(
974 &hdmi_dev->v4l2_dev, adapter,
975 pdata->mhl_info, NULL);
976
977 i2c_put_adapter(adapter);
978 if (hdmi_dev->mhl_sd == NULL) {
979 dev_err(dev, "missing subdev for MHL\n");
980 ret = -ENODEV;
981 goto fail_vdev;
982 }
983 }
984
985 clk_enable(hdmi_dev->res.hdmi);
986
987 pm_runtime_enable(dev);
988
989 sd = &hdmi_dev->sd;
990 v4l2_subdev_init(sd, &hdmi_sd_ops);
991 sd->owner = THIS_MODULE;
992
993 strlcpy(sd->name, "s5p-hdmi", sizeof sd->name);
994 hdmi_dev->cur_preset = HDMI_DEFAULT_PRESET;
995
996 hdmi_dev->cur_conf = hdmi_preset2conf(hdmi_dev->cur_preset);
997
998
999 dev_set_drvdata(dev, sd);
1000
1001 dev_info(dev, "probe successful\n");
1002
1003 return 0;
1004
1005fail_vdev:
1006 v4l2_device_unregister(&hdmi_dev->v4l2_dev);
1007
1008fail_init:
1009 hdmi_resources_cleanup(hdmi_dev);
1010
1011fail:
1012 dev_err(dev, "probe failed\n");
1013 return ret;
1014}
1015
1016static int __devexit hdmi_remove(struct platform_device *pdev)
1017{
1018 struct device *dev = &pdev->dev;
1019 struct v4l2_subdev *sd = dev_get_drvdata(dev);
1020 struct hdmi_device *hdmi_dev = sd_to_hdmi_dev(sd);
1021
1022 pm_runtime_disable(dev);
1023 clk_disable(hdmi_dev->res.hdmi);
1024 v4l2_device_unregister(&hdmi_dev->v4l2_dev);
1025 disable_irq(hdmi_dev->irq);
1026 hdmi_resources_cleanup(hdmi_dev);
1027 dev_info(dev, "remove successful\n");
1028
1029 return 0;
1030}
1031
1032static struct platform_driver hdmi_driver __refdata = {
1033 .probe = hdmi_probe,
1034 .remove = __devexit_p(hdmi_remove),
1035 .id_table = hdmi_driver_types,
1036 .driver = {
1037 .name = "s5p-hdmi",
1038 .owner = THIS_MODULE,
1039 .pm = &hdmi_pm_ops,
1040 }
1041};
1042
1043module_platform_driver(hdmi_driver);
1044