14 #define pr_fmt(fmt) "s5p-tv (hdmi_drv): " fmt
16 #ifdef CONFIG_VIDEO_SAMSUNG_S5P_HDMI_DEBUG
20 #include <linux/kernel.h>
21 #include <linux/slab.h>
23 #include <linux/i2c.h>
26 #include <linux/module.h>
47 #define HDMI_DEFAULT_PRESET V4L2_DV_480P59_94
102 .name =
"s5pv210-hdmi",
104 .name =
"exynos4-hdmi",
127 value = (value &
mask) | (old & ~mask);
142 writeb(value >> 24, hdev->
regs + reg_id + 12);
168 HDMI_INTC_FLAG_HPD_UNPLUG);
173 HDMI_INTC_FLAG_HPD_PLUG);
179 static void hdmi_reg_init(
struct hdmi_device *hdev)
197 static void hdmi_timing_apply(
struct hdmi_device *hdev,
206 (t->
vact[0].beg << 11) | t->
vact[0].end);
208 (t->
vsyn[0].beg << 12) | t->
vsyn[0].end);
214 (t->
hact.end << 12) | t->
vact[1].end);
216 (t->
vact[1].end << 11) | t->
vact[1].beg);
218 (t->
vsyn[1].beg << 12) | t->
vsyn[1].end);
220 (vsyn_trans << 12) | vsyn_trans);
224 (t->
hact.end << 12) | t->
vact[0].end);
251 static int hdmi_conf_apply(
struct hdmi_device *hdmi_dev)
258 dev_dbg(dev,
"%s\n", __func__);
284 hdmi_reg_init(hdmi_dev);
287 hdmi_timing_apply(hdmi_dev, conf);
296 #define DUMPREG(reg_id) \
297 dev_dbg(hdev->dev, "%s:" #reg_id " = %08x\n", prefix, \
298 readl(hdev->regs + reg_id))
300 dev_dbg(hdev->
dev,
"%s: ---- CONTROL REGISTERS ----\n", prefix);
309 dev_dbg(hdev->
dev,
"%s: ---- CORE REGISTERS ----\n", prefix);
322 dev_dbg(hdev->
dev,
"%s: ---- CORE SYNC REGISTERS ----\n", prefix);
349 dev_dbg(hdev->
dev,
"%s: ---- TG REGISTERS ----\n", prefix);
383 .hact = { .beg = 138, .end = 858 },
385 .hsyn = { .beg = 16, .end = 16 + 62 },
387 .vact[0] = { .beg = 42 + 3, .end = 522 + 3 },
389 .vsyn[0] = { .beg = 6 + 3, .end = 12 + 3},
392 static const struct hdmi_timings hdmi_timings_576p50 = {
393 .hact = { .beg = 144, .end = 864 },
395 .hsyn = { .beg = 12, .end = 12 + 64 },
397 .vact[0] = { .beg = 44 + 5, .end = 620 + 5 },
399 .vsyn[0] = { .beg = 0 + 5, .end = 5 + 5},
402 static const struct hdmi_timings hdmi_timings_720p60 = {
403 .hact = { .beg = 370, .end = 1650 },
405 .hsyn = { .beg = 110, .end = 110 + 40 },
407 .vact[0] = { .beg = 25 + 5, .end = 745 + 5 },
409 .vsyn[0] = { .beg = 0 + 5, .end = 5 + 5},
412 static const struct hdmi_timings hdmi_timings_720p50 = {
413 .hact = { .beg = 700, .end = 1980 },
415 .hsyn = { .beg = 440, .end = 440 + 40 },
417 .vact[0] = { .beg = 25 + 5, .end = 745 + 5 },
419 .vsyn[0] = { .beg = 0 + 5, .end = 5 + 5},
422 static const struct hdmi_timings hdmi_timings_1080p24 = {
423 .hact = { .beg = 830, .end = 2750 },
425 .hsyn = { .beg = 638, .end = 638 + 44 },
427 .vact[0] = { .beg = 41 + 4, .end = 1121 + 4 },
429 .vsyn[0] = { .beg = 0 + 4, .end = 5 + 4},
432 static const struct hdmi_timings hdmi_timings_1080p60 = {
433 .hact = { .beg = 280, .end = 2200 },
435 .hsyn = { .beg = 88, .end = 88 + 44 },
437 .vact[0] = { .beg = 41 + 4, .end = 1121 + 4 },
439 .vsyn[0] = { .beg = 0 + 4, .end = 5 + 4},
442 static const struct hdmi_timings hdmi_timings_1080i60 = {
443 .hact = { .beg = 280, .end = 2200 },
445 .hsyn = { .beg = 88, .end = 88 + 44 },
447 .vact[0] = { .beg = 20 + 2, .end = 560 + 2 },
448 .vact[1] = { .beg = 583 + 2, .end = 1123 + 2 },
451 .vsyn[0] = { .beg = 0 + 2, .end = 5 + 2},
452 .vsyn[1] = { .beg = 562 + 2, .end = 567 + 2},
455 static const struct hdmi_timings hdmi_timings_1080i50 = {
456 .hact = { .beg = 720, .end = 2640 },
458 .hsyn = { .beg = 528, .end = 528 + 44 },
460 .vact[0] = { .beg = 20 + 2, .end = 560 + 2 },
461 .vact[1] = { .beg = 583 + 2, .end = 1123 + 2 },
464 .vsyn[0] = { .beg = 0 + 2, .end = 5 + 2},
465 .vsyn[1] = { .beg = 562 + 2, .end = 567 + 2},
468 static const struct hdmi_timings hdmi_timings_1080p50 = {
469 .hact = { .beg = 720, .end = 2640 },
471 .hsyn = { .beg = 528, .end = 528 + 44 },
473 .vact[0] = { .beg = 41 + 4, .end = 1121 + 4 },
475 .vsyn[0] = { .beg = 0 + 4, .end = 5 + 4},
478 static const struct {
511 dev_dbg(dev,
"%s\n", __func__);
513 ret = hdmi_conf_apply(hdev);
522 for (tries = 100; tries; --tries) {
530 dev_err(dev,
"hdmiphy's pll could not reach steady state.\n");
532 hdmi_dumpregs(hdev,
"hdmiphy - s_stream");
538 if (hdev->
mhl_sd && ret) {
540 hdmi_dumpregs(hdev,
"mhl - s_stream");
552 hdmi_dumpregs(hdev,
"streamon");
556 static int hdmi_streamoff(
struct hdmi_device *hdev)
561 dev_dbg(dev,
"%s\n", __func__);
574 hdmi_dumpregs(hdev,
"streamoff");
583 dev_dbg(dev,
"%s(%d)\n", __func__, enable);
585 return hdmi_streamon(hdev);
586 return hdmi_streamoff(hdev);
611 static int hdmi_s_power(
struct v4l2_subdev *sd,
int on)
617 ret = pm_runtime_get_sync(hdev->
dev);
619 ret = pm_runtime_put_sync(hdev->
dev);
624 static int hdmi_s_dv_preset(
struct v4l2_subdev *sd,
631 conf = hdmi_preset2timings(preset->
preset);
642 static int hdmi_g_dv_preset(
struct v4l2_subdev *sd,
645 memset(preset, 0,
sizeof(*preset));
646 preset->
preset = sd_to_hdmi_dev(sd)->cur_preset;
651 struct v4l2_mbus_framefmt *
fmt)
659 memset(fmt, 0,
sizeof *fmt);
660 fmt->width = t->
hact.end - t->
hact.beg;
661 fmt->height = t->
vact[0].end - t->
vact[0].beg;
673 static int hdmi_enum_dv_presets(
struct v4l2_subdev *sd,
683 .s_power = hdmi_s_power,
687 .s_dv_preset = hdmi_s_dv_preset,
688 .g_dv_preset = hdmi_g_dv_preset,
689 .enum_dv_presets = hdmi_enum_dv_presets,
690 .g_mbus_fmt = hdmi_g_mbus_fmt,
691 .s_stream = hdmi_s_stream,
695 .core = &hdmi_sd_core_ops,
696 .video = &hdmi_sd_video_ops,
699 static int hdmi_runtime_suspend(
struct device *dev)
704 dev_dbg(dev,
"%s\n", __func__);
706 hdmi_resource_poweroff(&hdev->
res);
712 static int hdmi_runtime_resume(
struct device *dev)
718 dev_dbg(dev,
"%s\n", __func__);
720 hdmi_resource_poweron(&hdev->
res);
727 dev_dbg(dev,
"poweron succeed\n");
732 hdmi_resource_poweroff(&hdev->
res);
733 dev_err(dev,
"poweron failed\n");
738 static const struct dev_pm_ops hdmi_pm_ops = {
739 .runtime_suspend = hdmi_runtime_suspend,
740 .runtime_resume = hdmi_runtime_resume,
743 static void hdmi_resources_cleanup(
struct hdmi_device *hdev)
747 dev_dbg(hdev->
dev,
"HDMI resource cleanup\n");
753 if (!IS_ERR_OR_NULL(res->
hdmiphy))
761 if (!IS_ERR_OR_NULL(res->
hdmi))
763 memset(res, 0,
sizeof *res);
766 static int hdmi_resources_init(
struct hdmi_device *hdev)
770 static char *supply[] = {
778 dev_dbg(dev,
"HDMI resource init\n");
780 memset(res, 0,
sizeof *res);
784 if (IS_ERR_OR_NULL(res->
hdmi)) {
785 dev_err(dev,
"failed to get clock 'hdmi'\n");
790 dev_err(dev,
"failed to get clock 'sclk_hdmi'\n");
795 dev_err(dev,
"failed to get clock 'sclk_pixel'\n");
800 dev_err(dev,
"failed to get clock 'sclk_hdmiphy'\n");
804 if (IS_ERR_OR_NULL(res->
hdmiphy)) {
805 dev_err(dev,
"failed to get clock 'hdmiphy'\n");
811 dev_err(dev,
"failed to get memory for regulators\n");
821 dev_err(dev,
"failed to get regulators\n");
828 dev_err(dev,
"HDMI resource init - failed\n");
829 hdmi_resources_cleanup(hdev);
846 dev_err(dev,
"platform data is missing\n");
853 dev_err(dev,
"out of memory\n");
860 ret = hdmi_resources_init(hdmi_dev);
867 dev_err(dev,
"get memory resource failed.\n");
875 dev_err(dev,
"register mapping failed.\n");
882 dev_err(dev,
"get interrupt resource failed.\n");
887 ret = devm_request_irq(&pdev->
dev, res->
start, hdmi_irq_handler, 0,
890 dev_err(dev,
"request interrupt failed.\n");
901 dev_err(dev,
"could not register v4l2 device.\n");
907 dev_err(dev,
"hdmiphy info is missing in platform data\n");
913 if (adapter ==
NULL) {
914 dev_err(dev,
"hdmiphy adapter request failed\n");
924 dev_err(dev,
"missing subdev for hdmiphy\n");
932 if (adapter ==
NULL) {
933 dev_err(dev,
"MHL adapter request failed\n");
944 dev_err(dev,
"missing subdev for MHL\n");
967 dev_info(dev,
"probe successful\n");
975 hdmi_resources_cleanup(hdmi_dev);
978 dev_err(dev,
"probe failed\n");
988 pm_runtime_disable(dev);
992 hdmi_resources_cleanup(hdmi_dev);
993 dev_info(dev,
"remove successful\n");
1001 .id_table = hdmi_driver_types,