2 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
10 #include <linux/clk.h>
11 #include <linux/clk-provider.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/rockchip/cpu.h>
16 #include <linux/regmap.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/phy/phy.h>
20 #include <drm/drm_of.h>
22 #include <drm/drm_crtc_helper.h>
23 #include <drm/drm_edid.h>
24 #include <drm/drm_encoder_slave.h>
25 #include <drm/bridge/dw_hdmi.h>
27 #include "rockchip_drm_drv.h"
28 #include "rockchip_drm_vop.h"
30 #define RK3228_GRF_SOC_CON2 0x0408
31 #define RK3228_DDC_MASK_EN ((3 << 13) | (3 << (13 + 16)))
32 #define RK3228_GRF_SOC_CON6 0x0418
33 #define RK3228_IO_3V_DOMAIN ((7 << 4) | (7 << (4 + 16)))
35 #define RK3288_GRF_SOC_CON6 0x025C
36 #define RK3288_HDMI_LCDC_SEL BIT(4)
37 #define RK3366_GRF_SOC_CON0 0x0400
38 #define RK3366_HDMI_LCDC_SEL BIT(1)
39 #define RK3399_GRF_SOC_CON20 0x6250
40 #define RK3399_HDMI_LCDC_SEL BIT(6)
42 #define RK3328_GRF_SOC_CON2 0x0408
43 #define RK3328_DDC_MASK_EN ((3 << 10) | (3 << (10 + 16)))
44 #define RK3328_GRF_SOC_CON3 0x040c
45 #define RK3328_IO_CTRL_BY_HDMI (0xf0000000 | BIT(13) | BIT(12))
46 #define RK3328_GRF_SOC_CON4 0x0410
47 #define RK3328_IO_3V_DOMAIN (7 << (9 + 16))
48 #define RK3328_IO_5V_DOMAIN ((7 << 9) | (3 << (9 + 16)))
49 #define RK3328_HPD_3V (BIT(8 + 16) | BIT(13 + 16))
51 #define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
53 struct rockchip_hdmi {
55 struct regmap *regmap;
56 void __iomem *hdmiphy;
57 struct drm_encoder encoder;
58 enum dw_hdmi_devtype dev_type;
67 #define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x)
70 inno_dw_hdmi_phy_init(struct dw_hdmi *dw_hdmi, void *data,
71 struct drm_display_mode *mode)
73 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
75 return phy_power_on(hdmi->phy);
78 static void inno_dw_hdmi_phy_disable(struct dw_hdmi *dw_hdmi, void *data)
80 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
82 phy_power_off(hdmi->phy);
85 static enum drm_connector_status
86 inno_dw_hdmi_phy_read_hpd(struct dw_hdmi *dw_hdmi, void *data)
88 struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
89 enum drm_connector_status status;
91 status = dw_hdmi_phy_read_hpd(dw_hdmi, data);
93 if (hdmi->dev_type == RK3228_HDMI)
96 if (status == connector_status_connected)
97 regmap_write(hdmi->regmap,
101 regmap_write(hdmi->regmap,
103 RK3328_IO_3V_DOMAIN);
107 static int inno_dw_hdmi_init(struct rockchip_hdmi *hdmi)
111 ret = clk_prepare_enable(hdmi->grf_clk);
113 dev_err(hdmi->dev, "failed to enable grfclk %d\n", ret);
114 return -EPROBE_DEFER;
116 if (hdmi->dev_type == RK3328_HDMI) {
117 /* Map HPD pin to 3V io */
118 regmap_write(hdmi->regmap,
120 RK3328_IO_3V_DOMAIN |
122 /* Map ddc pin to 5V io */
123 regmap_write(hdmi->regmap,
125 RK3328_IO_CTRL_BY_HDMI);
126 regmap_write(hdmi->regmap,
131 regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON2,
133 regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON6,
134 RK3228_IO_3V_DOMAIN);
136 clk_disable_unprepare(hdmi->grf_clk);
141 * There are some rates that would be ranged for better clock jitter at
142 * Chrome OS tree, like 25.175Mhz would range to 25.170732Mhz. But due
143 * to the clock is aglined to KHz in struct drm_display_mode, this would
144 * bring some inaccurate error if we still run the compute_n math, so
145 * let's just code an const table for it until we can actually get the
148 static const struct dw_hdmi_audio_tmds_n rockchip_werid_tmds_n_table[] = {
149 /* 25176471 for 25.175 MHz = 428000000 / 17. */
150 { .tmds = 25177000, .n_32k = 4352, .n_44k1 = 14994, .n_48k = 6528, },
151 /* 57290323 for 57.284 MHz */
152 { .tmds = 57291000, .n_32k = 3968, .n_44k1 = 4557, .n_48k = 5952, },
153 /* 74437500 for 74.44 MHz = 297750000 / 4 */
154 { .tmds = 74438000, .n_32k = 8192, .n_44k1 = 18816, .n_48k = 4096, },
155 /* 118666667 for 118.68 MHz */
156 { .tmds = 118667000, .n_32k = 4224, .n_44k1 = 5292, .n_48k = 6336, },
157 /* 121714286 for 121.75 MHz */
158 { .tmds = 121715000, .n_32k = 4480, .n_44k1 = 6174, .n_48k = 6272, },
159 /* 136800000 for 136.75 MHz */
160 { .tmds = 136800000, .n_32k = 4096, .n_44k1 = 5684, .n_48k = 6144, },
162 { .tmds = 0, .n_32k = 0, .n_44k1 = 0, .n_48k = 0, },
165 static const struct dw_hdmi_mpll_config rockchip_mpll_cfg[] = {
253 static const struct dw_hdmi_curr_ctrl rockchip_cur_ctr[] = {
254 /* pixelclk bpp8 bpp10 bpp12 */
256 600000000, { 0x0000, 0x0000, 0x0000 },
258 ~0UL, { 0x0000, 0x0000, 0x0000},
262 static struct dw_hdmi_phy_config rockchip_phy_config[] = {
263 /*pixelclk symbol term vlev*/
264 { 74250000, 0x8009, 0x0004, 0x0272},
265 { 165000000, 0x802b, 0x0004, 0x0209},
266 { 297000000, 0x8039, 0x0005, 0x028d},
267 { 594000000, 0x8039, 0x0000, 0x019d},
268 { ~0UL, 0x0000, 0x0000, 0x0000}
271 static int rockchip_hdmi_update_phy_table(struct rockchip_hdmi *hdmi,
277 if (phy_table_size > ARRAY_SIZE(rockchip_phy_config)) {
278 dev_err(hdmi->dev, "phy table array number is out of range\n");
282 for (i = 0; i < phy_table_size; i++) {
283 if (config[i * 4] != 0)
284 rockchip_phy_config[i].mpixelclock = (u64)config[i * 4];
286 rockchip_phy_config[i].mpixelclock = ~0UL;
287 rockchip_phy_config[i].term = (u16)config[i * 4 + 1];
288 rockchip_phy_config[i].sym_ctr = (u16)config[i * 4 + 2];
289 rockchip_phy_config[i].vlev_ctr = (u16)config[i * 4 + 3];
295 static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi)
297 struct device_node *np = hdmi->dev->of_node;
298 int ret, val, phy_table_size;
301 hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
302 if (IS_ERR(hdmi->regmap)) {
303 dev_err(hdmi->dev, "Unable to get rockchip,grf\n");
304 return PTR_ERR(hdmi->regmap);
307 hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll");
308 if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) {
309 hdmi->vpll_clk = NULL;
310 } else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) {
311 return -EPROBE_DEFER;
312 } else if (IS_ERR(hdmi->vpll_clk)) {
313 dev_err(hdmi->dev, "failed to get grf clock\n");
314 return PTR_ERR(hdmi->vpll_clk);
317 hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf");
318 if (PTR_ERR(hdmi->grf_clk) == -ENOENT) {
319 hdmi->grf_clk = NULL;
320 } else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) {
321 return -EPROBE_DEFER;
322 } else if (IS_ERR(hdmi->grf_clk)) {
323 dev_err(hdmi->dev, "failed to get grf clock\n");
324 return PTR_ERR(hdmi->grf_clk);
327 hdmi->hclk_vio = devm_clk_get(hdmi->dev, "hclk_vio");
328 if (PTR_ERR(hdmi->hclk_vio) == -ENOENT) {
329 hdmi->hclk_vio = NULL;
330 } else if (PTR_ERR(hdmi->hclk_vio) == -EPROBE_DEFER) {
331 return -EPROBE_DEFER;
332 } else if (IS_ERR(hdmi->hclk_vio)) {
333 dev_err(hdmi->dev, "failed to get hclk_vio clock\n");
334 return PTR_ERR(hdmi->hclk_vio);
337 hdmi->dclk = devm_clk_get(hdmi->dev, "dclk");
338 if (PTR_ERR(hdmi->dclk) == -ENOENT) {
340 } else if (PTR_ERR(hdmi->dclk) == -EPROBE_DEFER) {
341 return -EPROBE_DEFER;
342 } else if (IS_ERR(hdmi->dclk)) {
343 dev_err(hdmi->dev, "failed to get dclk\n");
344 return PTR_ERR(hdmi->dclk);
347 ret = clk_prepare_enable(hdmi->vpll_clk);
349 dev_err(hdmi->dev, "Failed to enable HDMI vpll: %d\n", ret);
353 ret = clk_prepare_enable(hdmi->hclk_vio);
355 dev_err(hdmi->dev, "Failed to eanble HDMI hclk_vio: %d\n",
360 if (of_get_property(np, "rockchip,phy-table", &val)) {
361 phy_config = kmalloc(val, GFP_KERNEL);
363 /* use default table when kmalloc failed. */
364 dev_err(hdmi->dev, "kmalloc phy table failed\n");
368 phy_table_size = val / 16;
369 of_property_read_u32_array(np, "rockchip,phy-table",
370 phy_config, val / sizeof(u32));
371 ret = rockchip_hdmi_update_phy_table(hdmi, phy_config,
379 dev_dbg(hdmi->dev, "use default hdmi phy table\n");
385 static enum drm_mode_status
386 dw_hdmi_rockchip_mode_valid(struct drm_connector *connector,
387 struct drm_display_mode *mode)
389 struct drm_encoder *encoder = connector->encoder;
390 enum drm_mode_status status = MODE_OK;
391 struct drm_device *dev = connector->dev;
392 struct rockchip_drm_private *priv = dev->dev_private;
393 struct drm_crtc *crtc;
396 * Pixel clocks we support are always < 2GHz and so fit in an
397 * int. We should make sure source rate does too so we don't get
398 * overflow when we multiply by 1000.
400 if (mode->clock > INT_MAX / 1000)
403 * If sink max TMDS clock < 340MHz, we should check the mode pixel
404 * clock > 340MHz is YCbCr420 or not.
406 if (mode->clock > 340000 &&
407 connector->display_info.max_tmds_clock < 340000 &&
408 !(mode->flags & DRM_MODE_FLAG_420_MASK))
412 const struct drm_connector_helper_funcs *funcs;
414 funcs = connector->helper_private;
415 if (funcs->atomic_best_encoder)
416 encoder = funcs->atomic_best_encoder(connector,
419 encoder = funcs->best_encoder(connector);
422 if (!encoder || !encoder->possible_crtcs)
425 * ensure all drm display mode can work, if someone want support more
426 * resolutions, please limit the possible_crtc, only connect to
429 drm_for_each_crtc(crtc, connector->dev) {
430 int pipe = drm_crtc_index(crtc);
431 const struct rockchip_crtc_funcs *funcs =
432 priv->crtc_funcs[pipe];
434 if (!(encoder->possible_crtcs & drm_crtc_mask(crtc)))
436 if (!funcs || !funcs->mode_valid)
439 status = funcs->mode_valid(crtc, mode,
440 DRM_MODE_CONNECTOR_HDMIA);
441 if (status != MODE_OK)
448 static const struct drm_encoder_funcs dw_hdmi_rockchip_encoder_funcs = {
449 .destroy = drm_encoder_cleanup,
452 static void dw_hdmi_rockchip_encoder_disable(struct drm_encoder *encoder)
454 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
456 clk_disable_unprepare(hdmi->dclk);
459 static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
461 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
462 struct drm_crtc *crtc = encoder->crtc;
463 u32 lcdsel_grf_reg, lcdsel_mask;
468 if (WARN_ON(!crtc || !crtc->state))
471 clk_set_rate(hdmi->vpll_clk,
472 crtc->state->adjusted_mode.crtc_clock * 1000);
474 clk_set_rate(hdmi->dclk, crtc->state->adjusted_mode.crtc_clock * 1000);
475 clk_prepare_enable(hdmi->dclk);
477 switch (hdmi->dev_type) {
479 lcdsel_grf_reg = RK3288_GRF_SOC_CON6;
480 lcdsel_mask = RK3288_HDMI_LCDC_SEL;
483 lcdsel_grf_reg = RK3366_GRF_SOC_CON0;
484 lcdsel_mask = RK3366_HDMI_LCDC_SEL;
487 lcdsel_grf_reg = RK3399_GRF_SOC_CON20;
488 lcdsel_mask = RK3399_HDMI_LCDC_SEL;
494 mux = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder);
496 val = HIWORD_UPDATE(lcdsel_mask, lcdsel_mask);
498 val = HIWORD_UPDATE(0, lcdsel_mask);
500 ret = clk_prepare_enable(hdmi->grf_clk);
502 dev_err(hdmi->dev, "failed to enable grfclk %d\n", ret);
506 regmap_write(hdmi->regmap, lcdsel_grf_reg, val);
507 dev_dbg(hdmi->dev, "vop %s output to hdmi\n",
508 (mux) ? "LIT" : "BIG");
510 clk_disable_unprepare(hdmi->grf_clk);
514 dw_hdmi_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
515 struct drm_crtc_state *crtc_state,
516 struct drm_connector_state *conn_state)
518 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
519 struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
522 if (drm_match_cea_mode(&crtc_state->mode) > 94 &&
523 crtc_state->mode.crtc_clock > 340000 &&
524 !(crtc_state->mode.flags & DRM_MODE_FLAG_420_MASK)) {
525 crtc_state->mode.flags |= DRM_MODE_FLAG_420;
526 phy_set_bus_width(hdmi->phy, 4);
528 phy_set_bus_width(hdmi->phy, 8);
532 if (crtc_state->mode.flags & DRM_MODE_FLAG_420_MASK) {
533 s->output_mode = ROCKCHIP_OUT_MODE_YUV420;
534 s->bus_format = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
536 s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
537 s->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
539 s->output_type = DRM_MODE_CONNECTOR_HDMIA;
544 static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
545 .enable = dw_hdmi_rockchip_encoder_enable,
546 .disable = dw_hdmi_rockchip_encoder_disable,
547 .atomic_check = dw_hdmi_rockchip_encoder_atomic_check,
550 static const struct dw_hdmi_phy_ops inno_dw_hdmi_phy_ops = {
551 .init = inno_dw_hdmi_phy_init,
552 .disable = inno_dw_hdmi_phy_disable,
553 .read_hpd = inno_dw_hdmi_phy_read_hpd,
556 static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = {
557 .mode_valid = dw_hdmi_rockchip_mode_valid,
558 .phy_ops = &inno_dw_hdmi_phy_ops,
559 .phy_name = "inno_dw_hdmi_phy",
560 .dev_type = RK3228_HDMI,
563 static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = {
564 .mode_valid = dw_hdmi_rockchip_mode_valid,
565 .mpll_cfg = rockchip_mpll_cfg,
566 .cur_ctr = rockchip_cur_ctr,
567 .phy_config = rockchip_phy_config,
568 .dev_type = RK3288_HDMI,
569 .tmds_n_table = rockchip_werid_tmds_n_table,
572 static const struct dw_hdmi_plat_data rk3328_hdmi_drv_data = {
573 .mode_valid = dw_hdmi_rockchip_mode_valid,
574 .phy_ops = &inno_dw_hdmi_phy_ops,
575 .phy_name = "inno_dw_hdmi_phy2",
576 .dev_type = RK3328_HDMI,
579 static const struct dw_hdmi_plat_data rk3366_hdmi_drv_data = {
580 .mode_valid = dw_hdmi_rockchip_mode_valid,
581 .mpll_cfg = rockchip_mpll_cfg,
582 .cur_ctr = rockchip_cur_ctr,
583 .phy_config = rockchip_phy_config,
584 .dev_type = RK3366_HDMI,
587 static const struct dw_hdmi_plat_data rk3368_hdmi_drv_data = {
588 .mode_valid = dw_hdmi_rockchip_mode_valid,
589 .mpll_cfg = rockchip_mpll_cfg,
590 .cur_ctr = rockchip_cur_ctr,
591 .phy_config = rockchip_phy_config,
592 .dev_type = RK3368_HDMI,
595 static const struct dw_hdmi_plat_data rk3399_hdmi_drv_data = {
596 .mode_valid = dw_hdmi_rockchip_mode_valid,
597 .mpll_cfg = rockchip_mpll_cfg,
598 .cur_ctr = rockchip_cur_ctr,
599 .phy_config = rockchip_phy_config,
600 .dev_type = RK3399_HDMI,
603 static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
604 { .compatible = "rockchip,rk3228-dw-hdmi",
605 .data = &rk3228_hdmi_drv_data
607 { .compatible = "rockchip,rk3288-dw-hdmi",
608 .data = &rk3288_hdmi_drv_data
611 .compatible = "rockchip,rk3328-dw-hdmi",
612 .data = &rk3328_hdmi_drv_data
615 .compatible = "rockchip,rk3366-dw-hdmi",
616 .data = &rk3366_hdmi_drv_data
619 .compatible = "rockchip,rk3368-dw-hdmi",
620 .data = &rk3368_hdmi_drv_data
622 { .compatible = "rockchip,rk3399-dw-hdmi",
623 .data = &rk3399_hdmi_drv_data
627 MODULE_DEVICE_TABLE(of, dw_hdmi_rockchip_dt_ids);
629 static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
632 struct platform_device *pdev = to_platform_device(dev);
633 struct dw_hdmi_plat_data *plat_data;
634 const struct of_device_id *match;
635 struct drm_device *drm = data;
636 struct drm_encoder *encoder;
637 struct rockchip_hdmi *hdmi;
638 struct resource *iores;
642 if (!pdev->dev.of_node)
645 hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
649 match = of_match_node(dw_hdmi_rockchip_dt_ids, pdev->dev.of_node);
650 plat_data = (struct dw_hdmi_plat_data *)match->data;
651 hdmi->dev = &pdev->dev;
652 hdmi->dev_type = plat_data->dev_type;
653 encoder = &hdmi->encoder;
655 irq = platform_get_irq(pdev, 0);
659 iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
663 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
665 * If we failed to find the CRTC(s) which this encoder is
666 * supposed to be connected to, it's because the CRTC has
667 * not been registered yet. Defer probing, and hope that
668 * the required CRTC is added later.
670 if (encoder->possible_crtcs == 0)
671 return -EPROBE_DEFER;
673 ret = rockchip_hdmi_parse_dt(hdmi);
675 dev_err(hdmi->dev, "Unable to parse OF data\n");
679 if (hdmi->dev_type == RK3328_HDMI || hdmi->dev_type == RK3228_HDMI) {
680 hdmi->phy = devm_phy_get(dev, "hdmi_phy");
681 if (IS_ERR(hdmi->phy)) {
682 ret = PTR_ERR(hdmi->phy);
683 dev_err(dev, "failed to get phy: %d\n", ret);
686 plat_data->phy_data = hdmi;
687 ret = inno_dw_hdmi_init(hdmi);
692 drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
693 drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
694 DRM_MODE_ENCODER_TMDS, NULL);
696 ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data);
699 * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(),
700 * which would have called the encoder cleanup. Do it manually.
703 drm_encoder_cleanup(encoder);
708 static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master,
711 return dw_hdmi_unbind(dev, master, data);
714 static const struct component_ops dw_hdmi_rockchip_ops = {
715 .bind = dw_hdmi_rockchip_bind,
716 .unbind = dw_hdmi_rockchip_unbind,
719 static int dw_hdmi_rockchip_probe(struct platform_device *pdev)
721 pm_runtime_enable(&pdev->dev);
722 pm_runtime_get_sync(&pdev->dev);
724 return component_add(&pdev->dev, &dw_hdmi_rockchip_ops);
727 static int dw_hdmi_rockchip_remove(struct platform_device *pdev)
729 component_del(&pdev->dev, &dw_hdmi_rockchip_ops);
730 pm_runtime_disable(&pdev->dev);
735 static int dw_hdmi_rockchip_suspend(struct device *dev)
737 dw_hdmi_suspend(dev);
738 pm_runtime_put_sync(dev);
743 static int dw_hdmi_rockchip_resume(struct device *dev)
745 pm_runtime_get_sync(dev);
751 static const struct dev_pm_ops dw_hdmi_pm_ops = {
752 SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_rockchip_suspend,
753 dw_hdmi_rockchip_resume)
756 static struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
757 .probe = dw_hdmi_rockchip_probe,
758 .remove = dw_hdmi_rockchip_remove,
760 .name = "dwhdmi-rockchip",
761 .of_match_table = dw_hdmi_rockchip_dt_ids,
762 .pm = &dw_hdmi_pm_ops,
766 module_platform_driver(dw_hdmi_rockchip_pltfm_driver);
768 MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
769 MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
770 MODULE_DESCRIPTION("Rockchip Specific DW-HDMI Driver Extension");
771 MODULE_LICENSE("GPL");
772 MODULE_ALIAS("platform:dwhdmi-rockchip");