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 DVI mode */
214 hdmi_write_mask(hdev
, HDMI_MODE_SEL
,
215 HDMI_MODE_DVI_EN
, HDMI_MODE_MASK
);
216 hdmi_write_mask(hdev
, HDMI_CON_2
, ~0,
217 HDMI_DVI_PERAMBLE_EN
| HDMI_DVI_BAND_EN
);
218 /* disable bluescreen */
219 hdmi_write_mask(hdev
, HDMI_CON_0
, 0, HDMI_BLUE_SCR_EN
);
220 /* choose bluescreen (fecal) color */
221 hdmi_writeb(hdev
, HDMI_BLUE_SCREEN_0
, 0x12);
222 hdmi_writeb(hdev
, HDMI_BLUE_SCREEN_1
, 0x34);
223 hdmi_writeb(hdev
, HDMI_BLUE_SCREEN_2
, 0x56);
226 static void hdmi_timing_apply(struct hdmi_device
*hdev
,
227 const struct hdmi_preset_conf
*conf
)
229 const struct hdmi_core_regs
*core
= &conf
->core
;
230 const struct hdmi_tg_regs
*tg
= &conf
->tg
;
232 /* setting core registers */
233 hdmi_writeb(hdev
, HDMI_H_BLANK_0
, core
->h_blank
[0]);
234 hdmi_writeb(hdev
, HDMI_H_BLANK_1
, core
->h_blank
[1]);
235 hdmi_writeb(hdev
, HDMI_V_BLANK_0
, core
->v_blank
[0]);
236 hdmi_writeb(hdev
, HDMI_V_BLANK_1
, core
->v_blank
[1]);
237 hdmi_writeb(hdev
, HDMI_V_BLANK_2
, core
->v_blank
[2]);
238 hdmi_writeb(hdev
, HDMI_H_V_LINE_0
, core
->h_v_line
[0]);
239 hdmi_writeb(hdev
, HDMI_H_V_LINE_1
, core
->h_v_line
[1]);
240 hdmi_writeb(hdev
, HDMI_H_V_LINE_2
, core
->h_v_line
[2]);
241 hdmi_writeb(hdev
, HDMI_VSYNC_POL
, core
->vsync_pol
[0]);
242 hdmi_writeb(hdev
, HDMI_INT_PRO_MODE
, core
->int_pro_mode
[0]);
243 hdmi_writeb(hdev
, HDMI_V_BLANK_F_0
, core
->v_blank_f
[0]);
244 hdmi_writeb(hdev
, HDMI_V_BLANK_F_1
, core
->v_blank_f
[1]);
245 hdmi_writeb(hdev
, HDMI_V_BLANK_F_2
, core
->v_blank_f
[2]);
246 hdmi_writeb(hdev
, HDMI_H_SYNC_GEN_0
, core
->h_sync_gen
[0]);
247 hdmi_writeb(hdev
, HDMI_H_SYNC_GEN_1
, core
->h_sync_gen
[1]);
248 hdmi_writeb(hdev
, HDMI_H_SYNC_GEN_2
, core
->h_sync_gen
[2]);
249 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_1_0
, core
->v_sync_gen1
[0]);
250 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_1_1
, core
->v_sync_gen1
[1]);
251 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_1_2
, core
->v_sync_gen1
[2]);
252 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_2_0
, core
->v_sync_gen2
[0]);
253 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_2_1
, core
->v_sync_gen2
[1]);
254 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_2_2
, core
->v_sync_gen2
[2]);
255 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_3_0
, core
->v_sync_gen3
[0]);
256 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_3_1
, core
->v_sync_gen3
[1]);
257 hdmi_writeb(hdev
, HDMI_V_SYNC_GEN_3_2
, core
->v_sync_gen3
[2]);
258 /* Timing generator registers */
259 hdmi_writeb(hdev
, HDMI_TG_H_FSZ_L
, tg
->h_fsz_l
);
260 hdmi_writeb(hdev
, HDMI_TG_H_FSZ_H
, tg
->h_fsz_h
);
261 hdmi_writeb(hdev
, HDMI_TG_HACT_ST_L
, tg
->hact_st_l
);
262 hdmi_writeb(hdev
, HDMI_TG_HACT_ST_H
, tg
->hact_st_h
);
263 hdmi_writeb(hdev
, HDMI_TG_HACT_SZ_L
, tg
->hact_sz_l
);
264 hdmi_writeb(hdev
, HDMI_TG_HACT_SZ_H
, tg
->hact_sz_h
);
265 hdmi_writeb(hdev
, HDMI_TG_V_FSZ_L
, tg
->v_fsz_l
);
266 hdmi_writeb(hdev
, HDMI_TG_V_FSZ_H
, tg
->v_fsz_h
);
267 hdmi_writeb(hdev
, HDMI_TG_VSYNC_L
, tg
->vsync_l
);
268 hdmi_writeb(hdev
, HDMI_TG_VSYNC_H
, tg
->vsync_h
);
269 hdmi_writeb(hdev
, HDMI_TG_VSYNC2_L
, tg
->vsync2_l
);
270 hdmi_writeb(hdev
, HDMI_TG_VSYNC2_H
, tg
->vsync2_h
);
271 hdmi_writeb(hdev
, HDMI_TG_VACT_ST_L
, tg
->vact_st_l
);
272 hdmi_writeb(hdev
, HDMI_TG_VACT_ST_H
, tg
->vact_st_h
);
273 hdmi_writeb(hdev
, HDMI_TG_VACT_SZ_L
, tg
->vact_sz_l
);
274 hdmi_writeb(hdev
, HDMI_TG_VACT_SZ_H
, tg
->vact_sz_h
);
275 hdmi_writeb(hdev
, HDMI_TG_FIELD_CHG_L
, tg
->field_chg_l
);
276 hdmi_writeb(hdev
, HDMI_TG_FIELD_CHG_H
, tg
->field_chg_h
);
277 hdmi_writeb(hdev
, HDMI_TG_VACT_ST2_L
, tg
->vact_st2_l
);
278 hdmi_writeb(hdev
, HDMI_TG_VACT_ST2_H
, tg
->vact_st2_h
);
279 hdmi_writeb(hdev
, HDMI_TG_VSYNC_TOP_HDMI_L
, tg
->vsync_top_hdmi_l
);
280 hdmi_writeb(hdev
, HDMI_TG_VSYNC_TOP_HDMI_H
, tg
->vsync_top_hdmi_h
);
281 hdmi_writeb(hdev
, HDMI_TG_VSYNC_BOT_HDMI_L
, tg
->vsync_bot_hdmi_l
);
282 hdmi_writeb(hdev
, HDMI_TG_VSYNC_BOT_HDMI_H
, tg
->vsync_bot_hdmi_h
);
283 hdmi_writeb(hdev
, HDMI_TG_FIELD_TOP_HDMI_L
, tg
->field_top_hdmi_l
);
284 hdmi_writeb(hdev
, HDMI_TG_FIELD_TOP_HDMI_H
, tg
->field_top_hdmi_h
);
285 hdmi_writeb(hdev
, HDMI_TG_FIELD_BOT_HDMI_L
, tg
->field_bot_hdmi_l
);
286 hdmi_writeb(hdev
, HDMI_TG_FIELD_BOT_HDMI_H
, tg
->field_bot_hdmi_h
);
289 static int hdmi_conf_apply(struct hdmi_device
*hdmi_dev
)
291 struct device
*dev
= hdmi_dev
->dev
;
292 const struct hdmi_preset_conf
*conf
= hdmi_dev
->cur_conf
;
293 struct v4l2_dv_preset preset
;
296 dev_dbg(dev
, "%s\n", __func__
);
299 hdmi_write_mask(hdmi_dev
, HDMI_PHY_RSTOUT
, ~0, HDMI_PHY_SW_RSTOUT
);
301 hdmi_write_mask(hdmi_dev
, HDMI_PHY_RSTOUT
, 0, HDMI_PHY_SW_RSTOUT
);
304 /* configure presets */
305 preset
.preset
= hdmi_dev
->cur_preset
;
306 ret
= v4l2_subdev_call(hdmi_dev
->phy_sd
, video
, s_dv_preset
, &preset
);
308 dev_err(dev
, "failed to set preset (%u)\n", preset
.preset
);
312 /* resetting HDMI core */
313 hdmi_write_mask(hdmi_dev
, HDMI_CORE_RSTOUT
, 0, HDMI_CORE_SW_RSTOUT
);
315 hdmi_write_mask(hdmi_dev
, HDMI_CORE_RSTOUT
, ~0, HDMI_CORE_SW_RSTOUT
);
318 hdmi_reg_init(hdmi_dev
);
320 /* setting core registers */
321 hdmi_timing_apply(hdmi_dev
, conf
);
326 static void hdmi_dumpregs(struct hdmi_device
*hdev
, char *prefix
)
328 #define DUMPREG(reg_id) \
329 dev_dbg(hdev->dev, "%s:" #reg_id " = %08x\n", prefix, \
330 readl(hdev->regs + reg_id))
332 dev_dbg(hdev
->dev
, "%s: ---- CONTROL REGISTERS ----\n", prefix
);
333 DUMPREG(HDMI_INTC_FLAG
);
334 DUMPREG(HDMI_INTC_CON
);
335 DUMPREG(HDMI_HPD_STATUS
);
336 DUMPREG(HDMI_PHY_RSTOUT
);
337 DUMPREG(HDMI_PHY_VPLL
);
338 DUMPREG(HDMI_PHY_CMU
);
339 DUMPREG(HDMI_CORE_RSTOUT
);
341 dev_dbg(hdev
->dev
, "%s: ---- CORE REGISTERS ----\n", prefix
);
345 DUMPREG(HDMI_SYS_STATUS
);
346 DUMPREG(HDMI_PHY_STATUS
);
347 DUMPREG(HDMI_STATUS_EN
);
349 DUMPREG(HDMI_MODE_SEL
);
350 DUMPREG(HDMI_HPD_GEN
);
351 DUMPREG(HDMI_DC_CONTROL
);
352 DUMPREG(HDMI_VIDEO_PATTERN_GEN
);
354 dev_dbg(hdev
->dev
, "%s: ---- CORE SYNC REGISTERS ----\n", prefix
);
355 DUMPREG(HDMI_H_BLANK_0
);
356 DUMPREG(HDMI_H_BLANK_1
);
357 DUMPREG(HDMI_V_BLANK_0
);
358 DUMPREG(HDMI_V_BLANK_1
);
359 DUMPREG(HDMI_V_BLANK_2
);
360 DUMPREG(HDMI_H_V_LINE_0
);
361 DUMPREG(HDMI_H_V_LINE_1
);
362 DUMPREG(HDMI_H_V_LINE_2
);
363 DUMPREG(HDMI_VSYNC_POL
);
364 DUMPREG(HDMI_INT_PRO_MODE
);
365 DUMPREG(HDMI_V_BLANK_F_0
);
366 DUMPREG(HDMI_V_BLANK_F_1
);
367 DUMPREG(HDMI_V_BLANK_F_2
);
368 DUMPREG(HDMI_H_SYNC_GEN_0
);
369 DUMPREG(HDMI_H_SYNC_GEN_1
);
370 DUMPREG(HDMI_H_SYNC_GEN_2
);
371 DUMPREG(HDMI_V_SYNC_GEN_1_0
);
372 DUMPREG(HDMI_V_SYNC_GEN_1_1
);
373 DUMPREG(HDMI_V_SYNC_GEN_1_2
);
374 DUMPREG(HDMI_V_SYNC_GEN_2_0
);
375 DUMPREG(HDMI_V_SYNC_GEN_2_1
);
376 DUMPREG(HDMI_V_SYNC_GEN_2_2
);
377 DUMPREG(HDMI_V_SYNC_GEN_3_0
);
378 DUMPREG(HDMI_V_SYNC_GEN_3_1
);
379 DUMPREG(HDMI_V_SYNC_GEN_3_2
);
381 dev_dbg(hdev
->dev
, "%s: ---- TG REGISTERS ----\n", prefix
);
382 DUMPREG(HDMI_TG_CMD
);
383 DUMPREG(HDMI_TG_H_FSZ_L
);
384 DUMPREG(HDMI_TG_H_FSZ_H
);
385 DUMPREG(HDMI_TG_HACT_ST_L
);
386 DUMPREG(HDMI_TG_HACT_ST_H
);
387 DUMPREG(HDMI_TG_HACT_SZ_L
);
388 DUMPREG(HDMI_TG_HACT_SZ_H
);
389 DUMPREG(HDMI_TG_V_FSZ_L
);
390 DUMPREG(HDMI_TG_V_FSZ_H
);
391 DUMPREG(HDMI_TG_VSYNC_L
);
392 DUMPREG(HDMI_TG_VSYNC_H
);
393 DUMPREG(HDMI_TG_VSYNC2_L
);
394 DUMPREG(HDMI_TG_VSYNC2_H
);
395 DUMPREG(HDMI_TG_VACT_ST_L
);
396 DUMPREG(HDMI_TG_VACT_ST_H
);
397 DUMPREG(HDMI_TG_VACT_SZ_L
);
398 DUMPREG(HDMI_TG_VACT_SZ_H
);
399 DUMPREG(HDMI_TG_FIELD_CHG_L
);
400 DUMPREG(HDMI_TG_FIELD_CHG_H
);
401 DUMPREG(HDMI_TG_VACT_ST2_L
);
402 DUMPREG(HDMI_TG_VACT_ST2_H
);
403 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L
);
404 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H
);
405 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L
);
406 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H
);
407 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L
);
408 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H
);
409 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L
);
410 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H
);
414 static const struct hdmi_preset_conf hdmi_conf_480p
= {
416 .h_blank
= {0x8a, 0x00},
417 .v_blank
= {0x0d, 0x6a, 0x01},
418 .h_v_line
= {0x0d, 0xa2, 0x35},
420 .int_pro_mode
= {0x00},
421 .v_blank_f
= {0x00, 0x00, 0x00},
422 .h_sync_gen
= {0x0e, 0x30, 0x11},
423 .v_sync_gen1
= {0x0f, 0x90, 0x00},
424 /* other don't care */
428 0x5a, 0x03, /* h_fsz */
429 0x8a, 0x00, 0xd0, 0x02, /* hact */
430 0x0d, 0x02, /* v_fsz */
431 0x01, 0x00, 0x33, 0x02, /* vsync */
432 0x2d, 0x00, 0xe0, 0x01, /* vact */
433 0x33, 0x02, /* field_chg */
434 0x49, 0x02, /* vact_st2 */
435 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
436 0x01, 0x00, 0x33, 0x02, /* field top/bot */
441 .code
= V4L2_MBUS_FMT_FIXED
, /* means RGB888 */
442 .field
= V4L2_FIELD_NONE
,
443 .colorspace
= V4L2_COLORSPACE_SRGB
,
447 static const struct hdmi_preset_conf hdmi_conf_720p60
= {
449 .h_blank
= {0x72, 0x01},
450 .v_blank
= {0xee, 0xf2, 0x00},
451 .h_v_line
= {0xee, 0x22, 0x67},
453 .int_pro_mode
= {0x00},
454 .v_blank_f
= {0x00, 0x00, 0x00}, /* don't care */
455 .h_sync_gen
= {0x6c, 0x50, 0x02},
456 .v_sync_gen1
= {0x0a, 0x50, 0x00},
457 /* other don't care */
461 0x72, 0x06, /* h_fsz */
462 0x72, 0x01, 0x00, 0x05, /* hact */
463 0xee, 0x02, /* v_fsz */
464 0x01, 0x00, 0x33, 0x02, /* vsync */
465 0x1e, 0x00, 0xd0, 0x02, /* vact */
466 0x33, 0x02, /* field_chg */
467 0x49, 0x02, /* vact_st2 */
468 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
469 0x01, 0x00, 0x33, 0x02, /* field top/bot */
474 .code
= V4L2_MBUS_FMT_FIXED
, /* means RGB888 */
475 .field
= V4L2_FIELD_NONE
,
476 .colorspace
= V4L2_COLORSPACE_SRGB
,
480 static const struct hdmi_preset_conf hdmi_conf_1080p50
= {
482 .h_blank
= {0xd0, 0x02},
483 .v_blank
= {0x65, 0x6c, 0x01},
484 .h_v_line
= {0x65, 0x04, 0xa5},
486 .int_pro_mode
= {0x00},
487 .v_blank_f
= {0x00, 0x00, 0x00}, /* don't care */
488 .h_sync_gen
= {0x0e, 0xea, 0x08},
489 .v_sync_gen1
= {0x09, 0x40, 0x00},
490 /* other don't care */
494 0x98, 0x08, /* h_fsz */
495 0x18, 0x01, 0x80, 0x07, /* hact */
496 0x65, 0x04, /* v_fsz */
497 0x01, 0x00, 0x33, 0x02, /* vsync */
498 0x2d, 0x00, 0x38, 0x04, /* vact */
499 0x33, 0x02, /* field_chg */
500 0x49, 0x02, /* vact_st2 */
501 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
502 0x01, 0x00, 0x33, 0x02, /* field top/bot */
507 .code
= V4L2_MBUS_FMT_FIXED
, /* means RGB888 */
508 .field
= V4L2_FIELD_NONE
,
509 .colorspace
= V4L2_COLORSPACE_SRGB
,
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
,
542 .colorspace
= V4L2_COLORSPACE_SRGB
,
546 static const struct {
548 const struct hdmi_preset_conf
*conf
;
550 { V4L2_DV_480P59_94
, &hdmi_conf_480p
},
551 { V4L2_DV_720P59_94
, &hdmi_conf_720p60
},
552 { V4L2_DV_1080P50
, &hdmi_conf_1080p50
},
553 { V4L2_DV_1080P30
, &hdmi_conf_1080p60
},
554 { V4L2_DV_1080P60
, &hdmi_conf_1080p60
},
557 static const struct hdmi_preset_conf
*hdmi_preset2conf(u32 preset
)
561 for (i
= 0; i
< ARRAY_SIZE(hdmi_conf
); ++i
)
562 if (hdmi_conf
[i
].preset
== preset
)
563 return hdmi_conf
[i
].conf
;
567 static int hdmi_streamon(struct hdmi_device
*hdev
)
569 struct device
*dev
= hdev
->dev
;
570 struct hdmi_resources
*res
= &hdev
->res
;
573 dev_dbg(dev
, "%s\n", __func__
);
575 ret
= v4l2_subdev_call(hdev
->phy_sd
, video
, s_stream
, 1);
579 /* waiting for HDMIPHY's PLL to get to steady state */
580 for (tries
= 100; tries
; --tries
) {
581 u32 val
= hdmi_read(hdev
, HDMI_PHY_STATUS
);
582 if (val
& HDMI_PHY_STATUS_READY
)
586 /* steady state not achieved */
588 dev_err(dev
, "hdmiphy's pll could not reach steady state.\n");
589 v4l2_subdev_call(hdev
->phy_sd
, video
, s_stream
, 0);
590 hdmi_dumpregs(hdev
, "s_stream");
594 /* hdmiphy clock is used for HDMI in streaming mode */
595 clk_disable(res
->sclk_hdmi
);
596 clk_set_parent(res
->sclk_hdmi
, res
->sclk_hdmiphy
);
597 clk_enable(res
->sclk_hdmi
);
599 /* enable HDMI and timing generator */
600 hdmi_write_mask(hdev
, HDMI_CON_0
, ~0, HDMI_EN
);
601 hdmi_write_mask(hdev
, HDMI_TG_CMD
, ~0, HDMI_TG_EN
);
602 hdmi_dumpregs(hdev
, "streamon");
606 static int hdmi_streamoff(struct hdmi_device
*hdev
)
608 struct device
*dev
= hdev
->dev
;
609 struct hdmi_resources
*res
= &hdev
->res
;
611 dev_dbg(dev
, "%s\n", __func__
);
613 hdmi_write_mask(hdev
, HDMI_CON_0
, 0, HDMI_EN
);
614 hdmi_write_mask(hdev
, HDMI_TG_CMD
, 0, HDMI_TG_EN
);
616 /* pixel(vpll) clock is used for HDMI in config mode */
617 clk_disable(res
->sclk_hdmi
);
618 clk_set_parent(res
->sclk_hdmi
, res
->sclk_pixel
);
619 clk_enable(res
->sclk_hdmi
);
621 v4l2_subdev_call(hdev
->phy_sd
, video
, s_stream
, 0);
623 hdmi_dumpregs(hdev
, "streamoff");
627 static int hdmi_s_stream(struct v4l2_subdev
*sd
, int enable
)
629 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
630 struct device
*dev
= hdev
->dev
;
632 dev_dbg(dev
, "%s(%d)\n", __func__
, enable
);
634 return hdmi_streamon(hdev
);
635 return hdmi_streamoff(hdev
);
638 static void hdmi_resource_poweron(struct hdmi_resources
*res
)
640 /* turn HDMI power on */
641 regulator_bulk_enable(res
->regul_count
, res
->regul_bulk
);
642 /* power-on hdmi physical interface */
643 clk_enable(res
->hdmiphy
);
644 /* use VPP as parent clock; HDMIPHY is not working yet */
645 clk_set_parent(res
->sclk_hdmi
, res
->sclk_pixel
);
647 clk_enable(res
->sclk_hdmi
);
650 static void hdmi_resource_poweroff(struct hdmi_resources
*res
)
652 /* turn clocks off */
653 clk_disable(res
->sclk_hdmi
);
654 /* power-off hdmiphy */
655 clk_disable(res
->hdmiphy
);
656 /* turn HDMI power off */
657 regulator_bulk_disable(res
->regul_count
, res
->regul_bulk
);
660 static int hdmi_s_power(struct v4l2_subdev
*sd
, int on
)
662 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
666 ret
= pm_runtime_get_sync(hdev
->dev
);
668 ret
= pm_runtime_put_sync(hdev
->dev
);
669 /* only values < 0 indicate errors */
670 return IS_ERR_VALUE(ret
) ? ret
: 0;
673 static int hdmi_s_dv_preset(struct v4l2_subdev
*sd
,
674 struct v4l2_dv_preset
*preset
)
676 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
677 struct device
*dev
= hdev
->dev
;
678 const struct hdmi_preset_conf
*conf
;
680 conf
= hdmi_preset2conf(preset
->preset
);
682 dev_err(dev
, "preset (%u) not supported\n", preset
->preset
);
685 hdev
->cur_conf
= conf
;
686 hdev
->cur_preset
= preset
->preset
;
690 static int hdmi_g_dv_preset(struct v4l2_subdev
*sd
,
691 struct v4l2_dv_preset
*preset
)
693 memset(preset
, 0, sizeof(*preset
));
694 preset
->preset
= sd_to_hdmi_dev(sd
)->cur_preset
;
698 static int hdmi_g_mbus_fmt(struct v4l2_subdev
*sd
,
699 struct v4l2_mbus_framefmt
*fmt
)
701 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
702 struct device
*dev
= hdev
->dev
;
704 dev_dbg(dev
, "%s\n", __func__
);
707 *fmt
= hdev
->cur_conf
->mbus_fmt
;
711 static int hdmi_enum_dv_presets(struct v4l2_subdev
*sd
,
712 struct v4l2_dv_enum_preset
*preset
)
714 if (preset
->index
>= ARRAY_SIZE(hdmi_conf
))
716 return v4l_fill_dv_preset_info(hdmi_conf
[preset
->index
].preset
, preset
);
719 static const struct v4l2_subdev_core_ops hdmi_sd_core_ops
= {
720 .s_power
= hdmi_s_power
,
723 static const struct v4l2_subdev_video_ops hdmi_sd_video_ops
= {
724 .s_dv_preset
= hdmi_s_dv_preset
,
725 .g_dv_preset
= hdmi_g_dv_preset
,
726 .enum_dv_presets
= hdmi_enum_dv_presets
,
727 .g_mbus_fmt
= hdmi_g_mbus_fmt
,
728 .s_stream
= hdmi_s_stream
,
731 static const struct v4l2_subdev_ops hdmi_sd_ops
= {
732 .core
= &hdmi_sd_core_ops
,
733 .video
= &hdmi_sd_video_ops
,
736 static int hdmi_runtime_suspend(struct device
*dev
)
738 struct v4l2_subdev
*sd
= dev_get_drvdata(dev
);
739 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
741 dev_dbg(dev
, "%s\n", __func__
);
742 hdmi_resource_poweroff(&hdev
->res
);
746 static int hdmi_runtime_resume(struct device
*dev
)
748 struct v4l2_subdev
*sd
= dev_get_drvdata(dev
);
749 struct hdmi_device
*hdev
= sd_to_hdmi_dev(sd
);
752 dev_dbg(dev
, "%s\n", __func__
);
754 hdmi_resource_poweron(&hdev
->res
);
756 ret
= hdmi_conf_apply(hdev
);
760 dev_dbg(dev
, "poweron succeed\n");
765 hdmi_resource_poweroff(&hdev
->res
);
766 dev_err(dev
, "poweron failed\n");
771 static const struct dev_pm_ops hdmi_pm_ops
= {
772 .runtime_suspend
= hdmi_runtime_suspend
,
773 .runtime_resume
= hdmi_runtime_resume
,
776 static void hdmi_resources_cleanup(struct hdmi_device
*hdev
)
778 struct hdmi_resources
*res
= &hdev
->res
;
780 dev_dbg(hdev
->dev
, "HDMI resource cleanup\n");
781 /* put clocks, power */
782 if (res
->regul_count
)
783 regulator_bulk_free(res
->regul_count
, res
->regul_bulk
);
784 /* kfree is NULL-safe */
785 kfree(res
->regul_bulk
);
786 if (!IS_ERR_OR_NULL(res
->hdmiphy
))
787 clk_put(res
->hdmiphy
);
788 if (!IS_ERR_OR_NULL(res
->sclk_hdmiphy
))
789 clk_put(res
->sclk_hdmiphy
);
790 if (!IS_ERR_OR_NULL(res
->sclk_pixel
))
791 clk_put(res
->sclk_pixel
);
792 if (!IS_ERR_OR_NULL(res
->sclk_hdmi
))
793 clk_put(res
->sclk_hdmi
);
794 if (!IS_ERR_OR_NULL(res
->hdmi
))
796 memset(res
, 0, sizeof *res
);
799 static int hdmi_resources_init(struct hdmi_device
*hdev
)
801 struct device
*dev
= hdev
->dev
;
802 struct hdmi_resources
*res
= &hdev
->res
;
803 static char *supply
[] = {
811 dev_dbg(dev
, "HDMI resource init\n");
813 memset(res
, 0, sizeof *res
);
814 /* get clocks, power */
816 res
->hdmi
= clk_get(dev
, "hdmi");
817 if (IS_ERR_OR_NULL(res
->hdmi
)) {
818 dev_err(dev
, "failed to get clock 'hdmi'\n");
821 res
->sclk_hdmi
= clk_get(dev
, "sclk_hdmi");
822 if (IS_ERR_OR_NULL(res
->sclk_hdmi
)) {
823 dev_err(dev
, "failed to get clock 'sclk_hdmi'\n");
826 res
->sclk_pixel
= clk_get(dev
, "sclk_pixel");
827 if (IS_ERR_OR_NULL(res
->sclk_pixel
)) {
828 dev_err(dev
, "failed to get clock 'sclk_pixel'\n");
831 res
->sclk_hdmiphy
= clk_get(dev
, "sclk_hdmiphy");
832 if (IS_ERR_OR_NULL(res
->sclk_hdmiphy
)) {
833 dev_err(dev
, "failed to get clock 'sclk_hdmiphy'\n");
836 res
->hdmiphy
= clk_get(dev
, "hdmiphy");
837 if (IS_ERR_OR_NULL(res
->hdmiphy
)) {
838 dev_err(dev
, "failed to get clock 'hdmiphy'\n");
841 res
->regul_bulk
= kcalloc(ARRAY_SIZE(supply
),
842 sizeof(res
->regul_bulk
[0]), GFP_KERNEL
);
843 if (!res
->regul_bulk
) {
844 dev_err(dev
, "failed to get memory for regulators\n");
847 for (i
= 0; i
< ARRAY_SIZE(supply
); ++i
) {
848 res
->regul_bulk
[i
].supply
= supply
[i
];
849 res
->regul_bulk
[i
].consumer
= NULL
;
852 ret
= regulator_bulk_get(dev
, ARRAY_SIZE(supply
), res
->regul_bulk
);
854 dev_err(dev
, "failed to get regulators\n");
857 res
->regul_count
= ARRAY_SIZE(supply
);
861 dev_err(dev
, "HDMI resource init - failed\n");
862 hdmi_resources_cleanup(hdev
);
866 static int __devinit
hdmi_probe(struct platform_device
*pdev
)
868 struct device
*dev
= &pdev
->dev
;
869 struct resource
*res
;
870 struct i2c_adapter
*phy_adapter
;
871 struct v4l2_subdev
*sd
;
872 struct hdmi_device
*hdmi_dev
= NULL
;
873 struct hdmi_driver_data
*drv_data
;
876 dev_dbg(dev
, "probe start\n");
878 hdmi_dev
= kzalloc(sizeof(*hdmi_dev
), GFP_KERNEL
);
880 dev_err(dev
, "out of memory\n");
887 ret
= hdmi_resources_init(hdmi_dev
);
891 /* mapping HDMI registers */
892 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
894 dev_err(dev
, "get memory resource failed.\n");
899 hdmi_dev
->regs
= ioremap(res
->start
, resource_size(res
));
900 if (hdmi_dev
->regs
== NULL
) {
901 dev_err(dev
, "register mapping failed.\n");
906 res
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
908 dev_err(dev
, "get interrupt resource failed.\n");
913 ret
= request_irq(res
->start
, hdmi_irq_handler
, 0, "hdmi", hdmi_dev
);
915 dev_err(dev
, "request interrupt failed.\n");
918 hdmi_dev
->irq
= res
->start
;
920 /* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
921 strlcpy(hdmi_dev
->v4l2_dev
.name
, dev_name(dev
),
922 sizeof(hdmi_dev
->v4l2_dev
.name
));
923 /* passing NULL owner prevents driver from erasing drvdata */
924 ret
= v4l2_device_register(NULL
, &hdmi_dev
->v4l2_dev
);
926 dev_err(dev
, "could not register v4l2 device.\n");
930 drv_data
= (struct hdmi_driver_data
*)
931 platform_get_device_id(pdev
)->driver_data
;
932 phy_adapter
= i2c_get_adapter(drv_data
->hdmiphy_bus
);
933 if (phy_adapter
== NULL
) {
934 dev_err(dev
, "adapter request failed\n");
939 hdmi_dev
->phy_sd
= v4l2_i2c_new_subdev_board(&hdmi_dev
->v4l2_dev
,
940 phy_adapter
, &hdmiphy_info
, NULL
);
941 /* on failure or not adapter is no longer useful */
942 i2c_put_adapter(phy_adapter
);
943 if (hdmi_dev
->phy_sd
== NULL
) {
944 dev_err(dev
, "missing subdev for hdmiphy\n");
949 clk_enable(hdmi_dev
->res
.hdmi
);
951 pm_runtime_enable(dev
);
954 v4l2_subdev_init(sd
, &hdmi_sd_ops
);
955 sd
->owner
= THIS_MODULE
;
957 strlcpy(sd
->name
, "s5p-hdmi", sizeof sd
->name
);
958 hdmi_dev
->cur_preset
= HDMI_DEFAULT_PRESET
;
959 /* FIXME: missing fail preset is not supported */
960 hdmi_dev
->cur_conf
= hdmi_preset2conf(hdmi_dev
->cur_preset
);
962 /* storing subdev for call that have only access to struct device */
963 dev_set_drvdata(dev
, sd
);
965 dev_info(dev
, "probe sucessful\n");
970 v4l2_device_unregister(&hdmi_dev
->v4l2_dev
);
973 free_irq(hdmi_dev
->irq
, hdmi_dev
);
976 iounmap(hdmi_dev
->regs
);
979 hdmi_resources_cleanup(hdmi_dev
);
985 dev_err(dev
, "probe failed\n");
989 static int __devexit
hdmi_remove(struct platform_device
*pdev
)
991 struct device
*dev
= &pdev
->dev
;
992 struct v4l2_subdev
*sd
= dev_get_drvdata(dev
);
993 struct hdmi_device
*hdmi_dev
= sd_to_hdmi_dev(sd
);
995 pm_runtime_disable(dev
);
996 clk_disable(hdmi_dev
->res
.hdmi
);
997 v4l2_device_unregister(&hdmi_dev
->v4l2_dev
);
998 disable_irq(hdmi_dev
->irq
);
999 free_irq(hdmi_dev
->irq
, hdmi_dev
);
1000 iounmap(hdmi_dev
->regs
);
1001 hdmi_resources_cleanup(hdmi_dev
);
1003 dev_info(dev
, "remove sucessful\n");
1008 static struct platform_driver hdmi_driver __refdata
= {
1009 .probe
= hdmi_probe
,
1010 .remove
= __devexit_p(hdmi_remove
),
1011 .id_table
= hdmi_driver_types
,
1014 .owner
= THIS_MODULE
,
1019 module_platform_driver(hdmi_driver
);