2 * Samsung HDMI interface driver
4 * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
6 * Tomasz Stanislawski, <t.stanislaws@samsung.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published
10 * by the Free Software Foundiation. either version 2 of the License,
11 * or (at your option) any later version
14 #ifdef CONFIG_VIDEO_SAMSUNG_S5P_HDMI_DEBUG
18 #include <linux/kernel.h>
19 #include <linux/slab.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>
33 #include <media/v4l2-common.h>
34 #include <media/v4l2-dev.h>
35 #include <media/v4l2-device.h>
37 #include "regs-hdmi.h"
39 MODULE_AUTHOR("Tomasz Stanislawski, <t.stanislaws@samsung.com>");
40 MODULE_DESCRIPTION("Samsung HDMI");
41 MODULE_LICENSE("GPL");
43 /* default preset configured on probe */
44 #define HDMI_DEFAULT_PRESET V4L2_DV_1080P60
46 struct hdmi_resources
{
48 struct clk
*sclk_hdmi
;
49 struct clk
*sclk_pixel
;
50 struct clk
*sclk_hdmiphy
;
52 struct regulator_bulk_data
*regul_bulk
;
57 /** base address of HDMI registers */
61 /** pointer to device parent */
63 /** subdev generated by HDMI device */
64 struct v4l2_subdev sd
;
65 /** V4L2 device structure */
66 struct v4l2_device v4l2_dev
;
67 /** subdev of HDMIPHY interface */
68 struct v4l2_subdev
*phy_sd
;
69 /** configuration of current graphic mode */
70 const struct hdmi_preset_conf
*cur_conf
;
73 /** other resources */
74 struct hdmi_resources res
;
77 struct hdmi_driver_data
{
113 struct hdmi_core_regs
{
126 struct hdmi_preset_conf
{
127 struct hdmi_core_regs core
;
128 struct hdmi_tg_regs tg
;
129 struct v4l2_mbus_framefmt mbus_fmt
;
132 /* I2C module and id for HDMIPHY */
133 static struct i2c_board_info hdmiphy_info
= {
134 I2C_BOARD_INFO("hdmiphy", 0x38),
137 static struct hdmi_driver_data hdmi_driver_data
[] = {
138 { .hdmiphy_bus
= 3 },
139 { .hdmiphy_bus
= 8 },
142 static struct platform_device_id hdmi_driver_types
[] = {
144 .name
= "s5pv210-hdmi",
145 .driver_data
= (unsigned long)&hdmi_driver_data
[0],
147 .name
= "exynos4-hdmi",
148 .driver_data
= (unsigned long)&hdmi_driver_data
[1],
154 static const struct v4l2_subdev_ops hdmi_sd_ops
;
156 static struct hdmi_device
*sd_to_hdmi_dev(struct v4l2_subdev
*sd
)
158 return container_of(sd
, struct hdmi_device
, sd
);
162 void hdmi_write(struct hdmi_device
*hdev
, u32 reg_id
, u32 value
)
164 writel(value
, hdev
->regs
+ reg_id
);
168 void hdmi_write_mask(struct hdmi_device
*hdev
, u32 reg_id
, u32 value
, u32 mask
)
170 u32 old
= readl(hdev
->regs
+ reg_id
);
171 value
= (value
& mask
) | (old
& ~mask
);
172 writel(value
, hdev
->regs
+ reg_id
);
176 void hdmi_writeb(struct hdmi_device
*hdev
, u32 reg_id
, u8 value
)
178 writeb(value
, hdev
->regs
+ reg_id
);
181 static inline u32
hdmi_read(struct hdmi_device
*hdev
, u32 reg_id
)
183 return readl(hdev
->regs
+ reg_id
);
186 static irqreturn_t
hdmi_irq_handler(int irq
, void *dev_data
)
188 struct hdmi_device
*hdev
= dev_data
;
192 intc_flag
= hdmi_read(hdev
, HDMI_INTC_FLAG
);
193 /* clearing flags for HPD plug/unplug */
194 if (intc_flag
& HDMI_INTC_FLAG_HPD_UNPLUG
) {
195 printk(KERN_INFO
"unplugged\n");
196 hdmi_write_mask(hdev
, HDMI_INTC_FLAG
, ~0,
197 HDMI_INTC_FLAG_HPD_UNPLUG
);
199 if (intc_flag
& HDMI_INTC_FLAG_HPD_PLUG
) {
200 printk(KERN_INFO
"plugged\n");
201 hdmi_write_mask(hdev
, HDMI_INTC_FLAG
, ~0,
202 HDMI_INTC_FLAG_HPD_PLUG
);
208 static void hdmi_reg_init(struct hdmi_device
*hdev
)
210 /* enable HPD interrupts */
211 hdmi_write_mask(hdev
, HDMI_INTC_CON
, ~0, HDMI_INTC_EN_GLOBAL
|
212 HDMI_INTC_EN_HPD_PLUG
| HDMI_INTC_EN_HPD_UNPLUG
);
213 /* choose HDMI mode */
214 hdmi_write_mask(hdev
, HDMI_MODE_SEL
,
215 HDMI_MODE_HDMI_EN
, HDMI_MODE_MASK
);
216 /* disable bluescreen */
217 hdmi_write_mask(hdev
, HDMI_CON_0
, 0, HDMI_BLUE_SCR_EN
);
218 /* choose bluescreen (fecal) color */
219 hdmi_writeb(hdev
, HDMI_BLUE_SCREEN_0
, 0x12);
220 hdmi_writeb(hdev
, HDMI_BLUE_SCREEN_1
, 0x34);
221 hdmi_writeb(hdev
, HDMI_BLUE_SCREEN_2
, 0x56);
222 /* enable AVI packet every vsync, fixes purple line problem */
223 hdmi_writeb(hdev
, HDMI_AVI_CON
, 0x02);
224 /* force YUV444, look to CEA-861-D, table 7 for more detail */
225 hdmi_writeb(hdev
, HDMI_AVI_BYTE(0), 2 << 5);
226 hdmi_write_mask(hdev
, HDMI_CON_1
, 2, 3 << 5);
229 static void hdmi_timing_apply(struct hdmi_device
*hdev
,
230 const struct hdmi_preset_conf
*conf
)
232 const struct hdmi_core_regs
*core
= &conf
->core
;
233 const struct hdmi_tg_regs
*tg
= &conf
->tg
;
235 /* setting core registers */
236 hdmi_writeb(hdev
, HDMI_H_BLANK_0
, core
->h_blank
[0]);
237 hdmi_writeb(hdev
, HDMI_H_BLANK_1
, core
->h_blank
[1]);
238 hdmi_writeb(hdev
, HDMI_V_BLANK_0
, core
->v_blank
[0]);
239 hdmi_writeb(hdev
, HDMI_V_BLANK_1
, core
->v_blank
[1]);
240 hdmi_writeb(hdev
, HDMI_V_BLANK_2
, core
->v_blank
[2]);
241 hdmi_writeb(hdev
, HDMI_H_V_LINE_0
, core
->h_v_line
[0]);
242 hdmi_writeb(hdev
, HDMI_H_V_LINE_1
, core
->h_v_line
[1]);
243 hdmi_writeb(hdev
, HDMI_H_V_LINE_2
, core
->h_v_line
[2]);
244 hdmi_writeb(hdev
, HDMI_VSYNC_POL
, core
->vsync_pol
[0]);
245 hdmi_writeb(hdev
, HDMI_INT_PRO_MODE
, core
->int_pro_mode
[0]);
246 hdmi_writeb(hdev
, HDMI_V_BLANK_F_0
, core
->v_blank_f
[0]);
247 hdmi_writeb(hdev
, HDMI_V_BLANK_F_1
, core
->v_blank_f
[1]);
248 hdmi_writeb(hdev
, HDMI_V_BLANK_F_2
, core
->v_blank_f
[2]);
249 hdmi_writeb(hdev
, HDMI_H_SYNC_GEN_0
, core
->h_sync_gen
[0]);
250 hdmi_writeb(hdev
, HDMI_H_SYNC_GEN_1
, core
->h_sync_gen
[1]);
251 hdmi_writeb(hdev
, HDMI_H_SYNC_GEN_2
, core
->h_sync_gen
[2]);
252 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_1_0
, core
->v_sync_gen1
[0]);
253 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_1_1
, core
->v_sync_gen1
[1]);
254 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_1_2
, core
->v_sync_gen1
[2]);
255 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_2_0
, core
->v_sync_gen2
[0]);
256 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_2_1
, core
->v_sync_gen2
[1]);
257 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_2_2
, core
->v_sync_gen2
[2]);
258 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_3_0
, core
->v_sync_gen3
[0]);
259 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_3_1
, core
->v_sync_gen3
[1]);
260 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_3_2
, core
->v_sync_gen3
[2]);
261 /* Timing generator registers */
262 hdmi_writeb(hdev
, HDMI_TG_H_FSZ_L
, tg
->h_fsz_l
);
263 hdmi_writeb(hdev
, HDMI_TG_H_FSZ_H
, tg
->h_fsz_h
);
264 hdmi_writeb(hdev
, HDMI_TG_HACT_ST_L
, tg
->hact_st_l
);
265 hdmi_writeb(hdev
, HDMI_TG_HACT_ST_H
, tg
->hact_st_h
);
266 hdmi_writeb(hdev
, HDMI_TG_HACT_SZ_L
, tg
->hact_sz_l
);
267 hdmi_writeb(hdev
, HDMI_TG_HACT_SZ_H
, tg
->hact_sz_h
);
268 hdmi_writeb(hdev
, HDMI_TG_V_FSZ_L
, tg
->v_fsz_l
);
269 hdmi_writeb(hdev
, HDMI_TG_V_FSZ_H
, tg
->v_fsz_h
);
270 hdmi_writeb(hdev
, HDMI_TG_VSYNC_L
, tg
->vsync_l
);
271 hdmi_writeb(hdev
, HDMI_TG_VSYNC_H
, tg
->vsync_h
);
272 hdmi_writeb(hdev
, HDMI_TG_VSYNC2_L
, tg
->vsync2_l
);
273 hdmi_writeb(hdev
, HDMI_TG_VSYNC2_H
, tg
->vsync2_h
);
274 hdmi_writeb(hdev
, HDMI_TG_VACT_ST_L
, tg
->vact_st_l
);
275 hdmi_writeb(hdev
, HDMI_TG_VACT_ST_H
, tg
->vact_st_h
);
276 hdmi_writeb(hdev
, HDMI_TG_VACT_SZ_L
, tg
->vact_sz_l
);
277 hdmi_writeb(hdev
, HDMI_TG_VACT_SZ_H
, tg
->vact_sz_h
);
278 hdmi_writeb(hdev
, HDMI_TG_FIELD_CHG_L
, tg
->field_chg_l
);
279 hdmi_writeb(hdev
, HDMI_TG_FIELD_CHG_H
, tg
->field_chg_h
);
280 hdmi_writeb(hdev
, HDMI_TG_VACT_ST2_L
, tg
->vact_st2_l
);
281 hdmi_writeb(hdev
, HDMI_TG_VACT_ST2_H
, tg
->vact_st2_h
);
282 hdmi_writeb(hdev
, HDMI_TG_VSYNC_TOP_HDMI_L
, tg
->vsync_top_hdmi_l
);
283 hdmi_writeb(hdev
, HDMI_TG_VSYNC_TOP_HDMI_H
, tg
->vsync_top_hdmi_h
);
284 hdmi_writeb(hdev
, HDMI_TG_VSYNC_BOT_HDMI_L
, tg
->vsync_bot_hdmi_l
);
285 hdmi_writeb(hdev
, HDMI_TG_VSYNC_BOT_HDMI_H
, tg
->vsync_bot_hdmi_h
);
286 hdmi_writeb(hdev
, HDMI_TG_FIELD_TOP_HDMI_L
, tg
->field_top_hdmi_l
);
287 hdmi_writeb(hdev
, HDMI_TG_FIELD_TOP_HDMI_H
, tg
->field_top_hdmi_h
);
288 hdmi_writeb(hdev
, HDMI_TG_FIELD_BOT_HDMI_L
, tg
->field_bot_hdmi_l
);
289 hdmi_writeb(hdev
, HDMI_TG_FIELD_BOT_HDMI_H
, tg
->field_bot_hdmi_h
);
292 static int hdmi_conf_apply(struct hdmi_device
*hdmi_dev
)
294 struct device
*dev
= hdmi_dev
->dev
;
295 const struct hdmi_preset_conf
*conf
= hdmi_dev
->cur_conf
;
296 struct v4l2_dv_preset preset
;
299 dev_dbg(dev
, "%s\n", __func__
);
302 hdmi_write_mask(hdmi_dev
, HDMI_PHY_RSTOUT
, ~0, HDMI_PHY_SW_RSTOUT
);
304 hdmi_write_mask(hdmi_dev
, HDMI_PHY_RSTOUT
, 0, HDMI_PHY_SW_RSTOUT
);
307 /* configure presets */
308 preset
.preset
= hdmi_dev
->cur_preset
;
309 ret
= v4l2_subdev_call(hdmi_dev
->phy_sd
, video
, s_dv_preset
, &preset
);
311 dev_err(dev
, "failed to set preset (%u)\n", preset
.preset
);
315 /* resetting HDMI core */
316 hdmi_write_mask(hdmi_dev
, HDMI_CORE_RSTOUT
, 0, HDMI_CORE_SW_RSTOUT
);
318 hdmi_write_mask(hdmi_dev
, HDMI_CORE_RSTOUT
, ~0, HDMI_CORE_SW_RSTOUT
);
321 hdmi_reg_init(hdmi_dev
);
323 /* setting core registers */
324 hdmi_timing_apply(hdmi_dev
, conf
);
329 static void hdmi_dumpregs(struct hdmi_device
*hdev
, char *prefix
)
331 #define DUMPREG(reg_id) \
332 dev_dbg(hdev->dev, "%s:" #reg_id " = %08x\n", prefix, \
333 readl(hdev->regs + reg_id))
335 dev_dbg(hdev
->dev
, "%s: ---- CONTROL REGISTERS ----\n", prefix
);
336 DUMPREG(HDMI_INTC_FLAG
);
337 DUMPREG(HDMI_INTC_CON
);
338 DUMPREG(HDMI_HPD_STATUS
);
339 DUMPREG(HDMI_PHY_RSTOUT
);
340 DUMPREG(HDMI_PHY_VPLL
);
341 DUMPREG(HDMI_PHY_CMU
);
342 DUMPREG(HDMI_CORE_RSTOUT
);
344 dev_dbg(hdev
->dev
, "%s: ---- CORE REGISTERS ----\n", prefix
);
348 DUMPREG(HDMI_SYS_STATUS
);
349 DUMPREG(HDMI_PHY_STATUS
);
350 DUMPREG(HDMI_STATUS_EN
);
352 DUMPREG(HDMI_MODE_SEL
);
353 DUMPREG(HDMI_HPD_GEN
);
354 DUMPREG(HDMI_DC_CONTROL
);
355 DUMPREG(HDMI_VIDEO_PATTERN_GEN
);
357 dev_dbg(hdev
->dev
, "%s: ---- CORE SYNC REGISTERS ----\n", prefix
);
358 DUMPREG(HDMI_H_BLANK_0
);
359 DUMPREG(HDMI_H_BLANK_1
);
360 DUMPREG(HDMI_V_BLANK_0
);
361 DUMPREG(HDMI_V_BLANK_1
);
362 DUMPREG(HDMI_V_BLANK_2
);
363 DUMPREG(HDMI_H_V_LINE_0
);
364 DUMPREG(HDMI_H_V_LINE_1
);
365 DUMPREG(HDMI_H_V_LINE_2
);
366 DUMPREG(HDMI_VSYNC_POL
);
367 DUMPREG(HDMI_INT_PRO_MODE
);
368 DUMPREG(HDMI_V_BLANK_F_0
);
369 DUMPREG(HDMI_V_BLANK_F_1
);
370 DUMPREG(HDMI_V_BLANK_F_2
);
371 DUMPREG(HDMI_H_SYNC_GEN_0
);
372 DUMPREG(HDMI_H_SYNC_GEN_1
);
373 DUMPREG(HDMI_H_SYNC_GEN_2
);
374 DUMPREG(HDMI_V_SYNC_GEN_1_0
);
375 DUMPREG(HDMI_V_SYNC_GEN_1_1
);
376 DUMPREG(HDMI_V_SYNC_GEN_1_2
);
377 DUMPREG(HDMI_V_SYNC_GEN_2_0
);
378 DUMPREG(HDMI_V_SYNC_GEN_2_1
);
379 DUMPREG(HDMI_V_SYNC_GEN_2_2
);
380 DUMPREG(HDMI_V_SYNC_GEN_3_0
);
381 DUMPREG(HDMI_V_SYNC_GEN_3_1
);
382 DUMPREG(HDMI_V_SYNC_GEN_3_2
);
384 dev_dbg(hdev
->dev
, "%s: ---- TG REGISTERS ----\n", prefix
);
385 DUMPREG(HDMI_TG_CMD
);
386 DUMPREG(HDMI_TG_H_FSZ_L
);
387 DUMPREG(HDMI_TG_H_FSZ_H
);
388 DUMPREG(HDMI_TG_HACT_ST_L
);
389 DUMPREG(HDMI_TG_HACT_ST_H
);
390 DUMPREG(HDMI_TG_HACT_SZ_L
);
391 DUMPREG(HDMI_TG_HACT_SZ_H
);
392 DUMPREG(HDMI_TG_V_FSZ_L
);
393 DUMPREG(HDMI_TG_V_FSZ_H
);
394 DUMPREG(HDMI_TG_VSYNC_L
);
395 DUMPREG(HDMI_TG_VSYNC_H
);
396 DUMPREG(HDMI_TG_VSYNC2_L
);
397 DUMPREG(HDMI_TG_VSYNC2_H
);
398 DUMPREG(HDMI_TG_VACT_ST_L
);
399 DUMPREG(HDMI_TG_VACT_ST_H
);
400 DUMPREG(HDMI_TG_VACT_SZ_L
);
401 DUMPREG(HDMI_TG_VACT_SZ_H
);
402 DUMPREG(HDMI_TG_FIELD_CHG_L
);
403 DUMPREG(HDMI_TG_FIELD_CHG_H
);
404 DUMPREG(HDMI_TG_VACT_ST2_L
);
405 DUMPREG(HDMI_TG_VACT_ST2_H
);
406 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L
);
407 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H
);
408 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L
);
409 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H
);
410 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L
);
411 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H
);
412 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L
);
413 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H
);
417 static const struct hdmi_preset_conf hdmi_conf_480p
= {
419 .h_blank
= {0x8a, 0x00},
420 .v_blank
= {0x0d, 0x6a, 0x01},
421 .h_v_line
= {0x0d, 0xa2, 0x35},
423 .int_pro_mode
= {0x00},
424 .v_blank_f
= {0x00, 0x00, 0x00},
425 .h_sync_gen
= {0x0e, 0x30, 0x11},
426 .v_sync_gen1
= {0x0f, 0x90, 0x00},
427 /* other don't care */
431 0x5a, 0x03, /* h_fsz */
432 0x8a, 0x00, 0xd0, 0x02, /* hact */
433 0x0d, 0x02, /* v_fsz */
434 0x01, 0x00, 0x33, 0x02, /* vsync */
435 0x2d, 0x00, 0xe0, 0x01, /* vact */
436 0x33, 0x02, /* field_chg */
437 0x49, 0x02, /* vact_st2 */
438 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
439 0x01, 0x00, 0x33, 0x02, /* field top/bot */
444 .code
= V4L2_MBUS_FMT_FIXED
, /* means RGB888 */
445 .field
= V4L2_FIELD_NONE
,
449 static const struct hdmi_preset_conf hdmi_conf_720p60
= {
451 .h_blank
= {0x72, 0x01},
452 .v_blank
= {0xee, 0xf2, 0x00},
453 .h_v_line
= {0xee, 0x22, 0x67},
455 .int_pro_mode
= {0x00},
456 .v_blank_f
= {0x00, 0x00, 0x00}, /* don't care */
457 .h_sync_gen
= {0x6c, 0x50, 0x02},
458 .v_sync_gen1
= {0x0a, 0x50, 0x00},
459 /* other don't care */
463 0x72, 0x06, /* h_fsz */
464 0x72, 0x01, 0x00, 0x05, /* hact */
465 0xee, 0x02, /* v_fsz */
466 0x01, 0x00, 0x33, 0x02, /* vsync */
467 0x1e, 0x00, 0xd0, 0x02, /* vact */
468 0x33, 0x02, /* field_chg */
469 0x49, 0x02, /* vact_st2 */
470 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
471 0x01, 0x00, 0x33, 0x02, /* field top/bot */
476 .code
= V4L2_MBUS_FMT_FIXED
, /* means RGB888 */
477 .field
= V4L2_FIELD_NONE
,
481 static const struct hdmi_preset_conf hdmi_conf_1080p50
= {
483 .h_blank
= {0xd0, 0x02},
484 .v_blank
= {0x65, 0x6c, 0x01},
485 .h_v_line
= {0x65, 0x04, 0xa5},
487 .int_pro_mode
= {0x00},
488 .v_blank_f
= {0x00, 0x00, 0x00}, /* don't care */
489 .h_sync_gen
= {0x0e, 0xea, 0x08},
490 .v_sync_gen1
= {0x09, 0x40, 0x00},
491 /* other don't care */
495 0x98, 0x08, /* h_fsz */
496 0x18, 0x01, 0x80, 0x07, /* hact */
497 0x65, 0x04, /* v_fsz */
498 0x01, 0x00, 0x33, 0x02, /* vsync */
499 0x2d, 0x00, 0x38, 0x04, /* vact */
500 0x33, 0x02, /* field_chg */
501 0x49, 0x02, /* vact_st2 */
502 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
503 0x01, 0x00, 0x33, 0x02, /* field top/bot */
508 .code
= V4L2_MBUS_FMT_FIXED
, /* means RGB888 */
509 .field
= V4L2_FIELD_NONE
,
513 static const struct hdmi_preset_conf hdmi_conf_1080p60
= {
515 .h_blank
= {0x18, 0x01},
516 .v_blank
= {0x65, 0x6c, 0x01},
517 .h_v_line
= {0x65, 0x84, 0x89},
519 .int_pro_mode
= {0x00},
520 .v_blank_f
= {0x00, 0x00, 0x00}, /* don't care */
521 .h_sync_gen
= {0x56, 0x08, 0x02},
522 .v_sync_gen1
= {0x09, 0x40, 0x00},
523 /* other don't care */
527 0x98, 0x08, /* h_fsz */
528 0x18, 0x01, 0x80, 0x07, /* hact */
529 0x65, 0x04, /* v_fsz */
530 0x01, 0x00, 0x33, 0x02, /* vsync */
531 0x2d, 0x00, 0x38, 0x04, /* vact */
532 0x33, 0x02, /* field_chg */
533 0x48, 0x02, /* vact_st2 */
534 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
535 0x01, 0x00, 0x33, 0x02, /* field top/bot */
540 .code
= V4L2_MBUS_FMT_FIXED
, /* means RGB888 */
541 .field
= V4L2_FIELD_NONE
,
545 static const struct {
547 const struct hdmi_preset_conf
*conf
;
549 { V4L2_DV_480P59_94
, &hdmi_conf_480p
},
550 { V4L2_DV_720P59_94
, &hdmi_conf_720p60
},
551 { V4L2_DV_1080P50
, &hdmi_conf_1080p50
},
552 { V4L2_DV_1080P30
, &hdmi_conf_1080p60
},
553 { V4L2_DV_1080P60
, &hdmi_conf_1080p60
},
556 static const struct hdmi_preset_conf
*hdmi_preset2conf(u32 preset
)
560 for (i
= 0; i
< ARRAY_SIZE(hdmi_conf
); ++i
)
561 if (hdmi_conf
[i
].preset
== preset
)
562 return hdmi_conf
[i
].conf
;
566 static int hdmi_streamon(struct hdmi_device
*hdev
)
568 struct device
*dev
= hdev
->dev
;
569 struct hdmi_resources
*res
= &hdev
->res
;
572 dev_dbg(dev
, "%s\n", __func__
);
574 ret
= v4l2_subdev_call(hdev
->phy_sd
, video
, s_stream
, 1);
578 /* waiting for HDMIPHY's PLL to get to steady state */
579 for (tries
= 100; tries
; --tries
) {
580 u32 val
= hdmi_read(hdev
, HDMI_PHY_STATUS
);
581 if (val
& HDMI_PHY_STATUS_READY
)
585 /* steady state not achieved */
587 dev_err(dev
, "hdmiphy's pll could not reach steady state.\n");
588 v4l2_subdev_call(hdev
->phy_sd
, video
, s_stream
, 0);
589 hdmi_dumpregs(hdev
, "s_stream");
593 /* hdmiphy clock is used for HDMI in streaming mode */
594 clk_disable(res
->sclk_hdmi
);
595 clk_set_parent(res
->sclk_hdmi
, res
->sclk_hdmiphy
);
596 clk_enable(res
->sclk_hdmi
);
598 /* enable HDMI and timing generator */
599 hdmi_write_mask(hdev
, HDMI_CON_0
, ~0, HDMI_EN
);
600 hdmi_write_mask(hdev
, HDMI_TG_CMD
, ~0, HDMI_TG_EN
);
601 hdmi_dumpregs(hdev
, "streamon");
605 static int hdmi_streamoff(struct hdmi_device
*hdev
)
607 struct device
*dev
= hdev
->dev
;
608 struct hdmi_resources
*res
= &hdev
->res
;
610 dev_dbg(dev
, "%s\n", __func__
);
612 hdmi_write_mask(hdev
, HDMI_CON_0
, 0, HDMI_EN
);
613 hdmi_write_mask(hdev
, HDMI_TG_CMD
, 0, HDMI_TG_EN
);
615 /* pixel(vpll) clock is used for HDMI in config mode */
616 clk_disable(res
->sclk_hdmi
);
617 clk_set_parent(res
->sclk_hdmi
, res
->sclk_pixel
);
618 clk_enable(res
->sclk_hdmi
);
620 v4l2_subdev_call(hdev
->phy_sd
, video
, s_stream
, 0);
622 hdmi_dumpregs(hdev
, "streamoff");
626 static int hdmi_s_stream(struct v4l2_subdev
*sd
, int enable
)
628 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
629 struct device
*dev
= hdev
->dev
;
631 dev_dbg(dev
, "%s(%d)\n", __func__
, enable
);
633 return hdmi_streamon(hdev
);
634 return hdmi_streamoff(hdev
);
637 static void hdmi_resource_poweron(struct hdmi_resources
*res
)
639 /* turn HDMI power on */
640 regulator_bulk_enable(res
->regul_count
, res
->regul_bulk
);
641 /* power-on hdmi physical interface */
642 clk_enable(res
->hdmiphy
);
643 /* use VPP as parent clock; HDMIPHY is not working yet */
644 clk_set_parent(res
->sclk_hdmi
, res
->sclk_pixel
);
646 clk_enable(res
->sclk_hdmi
);
649 static void hdmi_resource_poweroff(struct hdmi_resources
*res
)
651 /* turn clocks off */
652 clk_disable(res
->sclk_hdmi
);
653 /* power-off hdmiphy */
654 clk_disable(res
->hdmiphy
);
655 /* turn HDMI power off */
656 regulator_bulk_disable(res
->regul_count
, res
->regul_bulk
);
659 static int hdmi_s_power(struct v4l2_subdev
*sd
, int on
)
661 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
665 ret
= pm_runtime_get_sync(hdev
->dev
);
667 ret
= pm_runtime_put_sync(hdev
->dev
);
668 /* only values < 0 indicate errors */
669 return IS_ERR_VALUE(ret
) ? ret
: 0;
672 static int hdmi_s_dv_preset(struct v4l2_subdev
*sd
,
673 struct v4l2_dv_preset
*preset
)
675 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
676 struct device
*dev
= hdev
->dev
;
677 const struct hdmi_preset_conf
*conf
;
679 conf
= hdmi_preset2conf(preset
->preset
);
681 dev_err(dev
, "preset (%u) not supported\n", preset
->preset
);
684 hdev
->cur_conf
= conf
;
685 hdev
->cur_preset
= preset
->preset
;
689 static int hdmi_g_dv_preset(struct v4l2_subdev
*sd
,
690 struct v4l2_dv_preset
*preset
)
692 memset(preset
, 0, sizeof(*preset
));
693 preset
->preset
= sd_to_hdmi_dev(sd
)->cur_preset
;
697 static int hdmi_g_mbus_fmt(struct v4l2_subdev
*sd
,
698 struct v4l2_mbus_framefmt
*fmt
)
700 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
701 struct device
*dev
= hdev
->dev
;
703 dev_dbg(dev
, "%s\n", __func__
);
706 *fmt
= hdev
->cur_conf
->mbus_fmt
;
710 static int hdmi_enum_dv_presets(struct v4l2_subdev
*sd
,
711 struct v4l2_dv_enum_preset
*preset
)
713 if (preset
->index
>= ARRAY_SIZE(hdmi_conf
))
715 return v4l_fill_dv_preset_info(hdmi_conf
[preset
->index
].preset
, preset
);
718 static const struct v4l2_subdev_core_ops hdmi_sd_core_ops
= {
719 .s_power
= hdmi_s_power
,
722 static const struct v4l2_subdev_video_ops hdmi_sd_video_ops
= {
723 .s_dv_preset
= hdmi_s_dv_preset
,
724 .g_dv_preset
= hdmi_g_dv_preset
,
725 .enum_dv_presets
= hdmi_enum_dv_presets
,
726 .g_mbus_fmt
= hdmi_g_mbus_fmt
,
727 .s_stream
= hdmi_s_stream
,
730 static const struct v4l2_subdev_ops hdmi_sd_ops
= {
731 .core
= &hdmi_sd_core_ops
,
732 .video
= &hdmi_sd_video_ops
,
735 static int hdmi_runtime_suspend(struct device
*dev
)
737 struct v4l2_subdev
*sd
= dev_get_drvdata(dev
);
738 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
740 dev_dbg(dev
, "%s\n", __func__
);
741 hdmi_resource_poweroff(&hdev
->res
);
745 static int hdmi_runtime_resume(struct device
*dev
)
747 struct v4l2_subdev
*sd
= dev_get_drvdata(dev
);
748 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
751 dev_dbg(dev
, "%s\n", __func__
);
753 hdmi_resource_poweron(&hdev
->res
);
755 ret
= hdmi_conf_apply(hdev
);
759 dev_dbg(dev
, "poweron succeed\n");
764 hdmi_resource_poweroff(&hdev
->res
);
765 dev_err(dev
, "poweron failed\n");
770 static const struct dev_pm_ops hdmi_pm_ops
= {
771 .runtime_suspend
= hdmi_runtime_suspend
,
772 .runtime_resume
= hdmi_runtime_resume
,
775 static void hdmi_resources_cleanup(struct hdmi_device
*hdev
)
777 struct hdmi_resources
*res
= &hdev
->res
;
779 dev_dbg(hdev
->dev
, "HDMI resource cleanup\n");
780 /* put clocks, power */
781 if (res
->regul_count
)
782 regulator_bulk_free(res
->regul_count
, res
->regul_bulk
);
783 /* kfree is NULL-safe */
784 kfree(res
->regul_bulk
);
785 if (!IS_ERR_OR_NULL(res
->hdmiphy
))
786 clk_put(res
->hdmiphy
);
787 if (!IS_ERR_OR_NULL(res
->sclk_hdmiphy
))
788 clk_put(res
->sclk_hdmiphy
);
789 if (!IS_ERR_OR_NULL(res
->sclk_pixel
))
790 clk_put(res
->sclk_pixel
);
791 if (!IS_ERR_OR_NULL(res
->sclk_hdmi
))
792 clk_put(res
->sclk_hdmi
);
793 if (!IS_ERR_OR_NULL(res
->hdmi
))
795 memset(res
, 0, sizeof *res
);
798 static int hdmi_resources_init(struct hdmi_device
*hdev
)
800 struct device
*dev
= hdev
->dev
;
801 struct hdmi_resources
*res
= &hdev
->res
;
802 static char *supply
[] = {
810 dev_dbg(dev
, "HDMI resource init\n");
812 memset(res
, 0, sizeof *res
);
813 /* get clocks, power */
815 res
->hdmi
= clk_get(dev
, "hdmi");
816 if (IS_ERR_OR_NULL(res
->hdmi
)) {
817 dev_err(dev
, "failed to get clock 'hdmi'\n");
820 res
->sclk_hdmi
= clk_get(dev
, "sclk_hdmi");
821 if (IS_ERR_OR_NULL(res
->sclk_hdmi
)) {
822 dev_err(dev
, "failed to get clock 'sclk_hdmi'\n");
825 res
->sclk_pixel
= clk_get(dev
, "sclk_pixel");
826 if (IS_ERR_OR_NULL(res
->sclk_pixel
)) {
827 dev_err(dev
, "failed to get clock 'sclk_pixel'\n");
830 res
->sclk_hdmiphy
= clk_get(dev
, "sclk_hdmiphy");
831 if (IS_ERR_OR_NULL(res
->sclk_hdmiphy
)) {
832 dev_err(dev
, "failed to get clock 'sclk_hdmiphy'\n");
835 res
->hdmiphy
= clk_get(dev
, "hdmiphy");
836 if (IS_ERR_OR_NULL(res
->hdmiphy
)) {
837 dev_err(dev
, "failed to get clock 'hdmiphy'\n");
840 res
->regul_bulk
= kzalloc(ARRAY_SIZE(supply
) *
841 sizeof res
->regul_bulk
[0], GFP_KERNEL
);
842 if (!res
->regul_bulk
) {
843 dev_err(dev
, "failed to get memory for regulators\n");
846 for (i
= 0; i
< ARRAY_SIZE(supply
); ++i
) {
847 res
->regul_bulk
[i
].supply
= supply
[i
];
848 res
->regul_bulk
[i
].consumer
= NULL
;
851 ret
= regulator_bulk_get(dev
, ARRAY_SIZE(supply
), res
->regul_bulk
);
853 dev_err(dev
, "failed to get regulators\n");
856 res
->regul_count
= ARRAY_SIZE(supply
);
860 dev_err(dev
, "HDMI resource init - failed\n");
861 hdmi_resources_cleanup(hdev
);
865 static int __devinit
hdmi_probe(struct platform_device
*pdev
)
867 struct device
*dev
= &pdev
->dev
;
868 struct resource
*res
;
869 struct i2c_adapter
*phy_adapter
;
870 struct v4l2_subdev
*sd
;
871 struct hdmi_device
*hdmi_dev
= NULL
;
872 struct hdmi_driver_data
*drv_data
;
875 dev_dbg(dev
, "probe start\n");
877 hdmi_dev
= kzalloc(sizeof(*hdmi_dev
), GFP_KERNEL
);
879 dev_err(dev
, "out of memory\n");
886 ret
= hdmi_resources_init(hdmi_dev
);
890 /* mapping HDMI registers */
891 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
893 dev_err(dev
, "get memory resource failed.\n");
898 hdmi_dev
->regs
= ioremap(res
->start
, resource_size(res
));
899 if (hdmi_dev
->regs
== NULL
) {
900 dev_err(dev
, "register mapping failed.\n");
905 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
907 dev_err(dev
, "get interrupt resource failed.\n");
912 ret
= request_irq(res
->start
, hdmi_irq_handler
, 0, "hdmi", hdmi_dev
);
914 dev_err(dev
, "request interrupt failed.\n");
917 hdmi_dev
->irq
= res
->start
;
919 /* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
920 strlcpy(hdmi_dev
->v4l2_dev
.name
, dev_name(dev
),
921 sizeof(hdmi_dev
->v4l2_dev
.name
));
922 /* passing NULL owner prevents driver from erasing drvdata */
923 ret
= v4l2_device_register(NULL
, &hdmi_dev
->v4l2_dev
);
925 dev_err(dev
, "could not register v4l2 device.\n");
929 drv_data
= (struct hdmi_driver_data
*)
930 platform_get_device_id(pdev
)->driver_data
;
931 phy_adapter
= i2c_get_adapter(drv_data
->hdmiphy_bus
);
932 if (phy_adapter
== NULL
) {
933 dev_err(dev
, "adapter request failed\n");
938 hdmi_dev
->phy_sd
= v4l2_i2c_new_subdev_board(&hdmi_dev
->v4l2_dev
,
939 phy_adapter
, &hdmiphy_info
, NULL
);
940 /* on failure or not adapter is no longer useful */
941 i2c_put_adapter(phy_adapter
);
942 if (hdmi_dev
->phy_sd
== NULL
) {
943 dev_err(dev
, "missing subdev for hdmiphy\n");
948 clk_enable(hdmi_dev
->res
.hdmi
);
950 pm_runtime_enable(dev
);
953 v4l2_subdev_init(sd
, &hdmi_sd_ops
);
954 sd
->owner
= THIS_MODULE
;
956 strlcpy(sd
->name
, "s5p-hdmi", sizeof sd
->name
);
957 hdmi_dev
->cur_preset
= HDMI_DEFAULT_PRESET
;
958 /* FIXME: missing fail preset is not supported */
959 hdmi_dev
->cur_conf
= hdmi_preset2conf(hdmi_dev
->cur_preset
);
961 /* storing subdev for call that have only access to struct device */
962 dev_set_drvdata(dev
, sd
);
964 dev_info(dev
, "probe sucessful\n");
969 v4l2_device_unregister(&hdmi_dev
->v4l2_dev
);
972 free_irq(hdmi_dev
->irq
, hdmi_dev
);
975 iounmap(hdmi_dev
->regs
);
978 hdmi_resources_cleanup(hdmi_dev
);
984 dev_err(dev
, "probe failed\n");
988 static int __devexit
hdmi_remove(struct platform_device
*pdev
)
990 struct device
*dev
= &pdev
->dev
;
991 struct v4l2_subdev
*sd
= dev_get_drvdata(dev
);
992 struct hdmi_device
*hdmi_dev
= sd_to_hdmi_dev(sd
);
994 pm_runtime_disable(dev
);
995 clk_disable(hdmi_dev
->res
.hdmi
);
996 v4l2_device_unregister(&hdmi_dev
->v4l2_dev
);
997 disable_irq(hdmi_dev
->irq
);
998 free_irq(hdmi_dev
->irq
, hdmi_dev
);
999 iounmap(hdmi_dev
->regs
);
1000 hdmi_resources_cleanup(hdmi_dev
);
1002 dev_info(dev
, "remove sucessful\n");
1007 static struct platform_driver hdmi_driver __refdata
= {
1008 .probe
= hdmi_probe
,
1009 .remove
= __devexit_p(hdmi_remove
),
1010 .id_table
= hdmi_driver_types
,
1013 .owner
= THIS_MODULE
,
1018 /* D R I V E R I N I T I A L I Z A T I O N */
1020 static int __init
hdmi_init(void)
1023 static const char banner
[] __initdata
= KERN_INFO \
1024 "Samsung HDMI output driver, "
1025 "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
1028 ret
= platform_driver_register(&hdmi_driver
);
1030 printk(KERN_ERR
"HDMI platform driver register failed\n");
1034 module_init(hdmi_init
);
1036 static void __exit
hdmi_exit(void)
1038 platform_driver_unregister(&hdmi_driver
);
1040 module_exit(hdmi_exit
);