aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-10-10 21:44:01 -0400
committerDave Airlie <airlied@redhat.com>2018-10-10 21:44:09 -0400
commit66c9e573ea75b63602cf4d3e1fb52fad2dd29be0 (patch)
treed748287b23d5cd28e5e6ab174464987015d92d83 /drivers/gpu
parent7e6191d4360a2df6cf2a2613dcb79680cb943df8 (diff)
parent84dacb9cad2804a9f5434b775ccea6aa5d9fc6ca (diff)
Merge branch 'mediatek-drm-next-4.20' of https://github.com/ckhu-mediatek/linux.git-tags into drm-next
This include hdmi output support for mt2701 and mt7623. Signed-off-by: Dave Airlie <airlied@redhat.com> From: CK Hu <ck.hu@mediatek.com> Link: https://patchwork.freedesktop.org/patch/msgid/1538616148.28906.1.camel@mtksdaap41
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/mediatek/Makefile5
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c131
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi_regs.h2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp.c14
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.c15
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.h2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_phy.c235
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_phy.h60
-rw-r--r--drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c212
-rw-r--r--drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c226
12 files changed, 627 insertions, 279 deletions
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index ce83c396a742..82ae49c64221 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -1,4 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2
2mediatek-drm-y := mtk_disp_color.o \ 3mediatek-drm-y := mtk_disp_color.o \
3 mtk_disp_ovl.o \ 4 mtk_disp_ovl.o \
4 mtk_disp_rdma.o \ 5 mtk_disp_rdma.o \
@@ -18,6 +19,8 @@ obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
18mediatek-drm-hdmi-objs := mtk_cec.o \ 19mediatek-drm-hdmi-objs := mtk_cec.o \
19 mtk_hdmi.o \ 20 mtk_hdmi.o \
20 mtk_hdmi_ddc.o \ 21 mtk_hdmi_ddc.o \
21 mtk_mt8173_hdmi_phy.o 22 mtk_mt2701_hdmi_phy.o \
23 mtk_mt8173_hdmi_phy.o \
24 mtk_hdmi_phy.o
22 25
23obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o 26obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index 6c0ea39d5739..62a9d47df948 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -14,10 +14,12 @@
14#include <drm/drmP.h> 14#include <drm/drmP.h>
15#include <drm/drm_crtc.h> 15#include <drm/drm_crtc.h>
16#include <drm/drm_crtc_helper.h> 16#include <drm/drm_crtc_helper.h>
17#include <drm/drm_of.h>
17#include <linux/kernel.h> 18#include <linux/kernel.h>
18#include <linux/component.h> 19#include <linux/component.h>
19#include <linux/platform_device.h> 20#include <linux/platform_device.h>
20#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_device.h>
21#include <linux/of_graph.h> 23#include <linux/of_graph.h>
22#include <linux/interrupt.h> 24#include <linux/interrupt.h>
23#include <linux/types.h> 25#include <linux/types.h>
@@ -72,12 +74,12 @@ struct mtk_dpi {
72 struct clk *tvd_clk; 74 struct clk *tvd_clk;
73 int irq; 75 int irq;
74 struct drm_display_mode mode; 76 struct drm_display_mode mode;
77 const struct mtk_dpi_conf *conf;
75 enum mtk_dpi_out_color_format color_format; 78 enum mtk_dpi_out_color_format color_format;
76 enum mtk_dpi_out_yc_map yc_map; 79 enum mtk_dpi_out_yc_map yc_map;
77 enum mtk_dpi_out_bit_num bit_num; 80 enum mtk_dpi_out_bit_num bit_num;
78 enum mtk_dpi_out_channel_swap channel_swap; 81 enum mtk_dpi_out_channel_swap channel_swap;
79 bool power_sta; 82 int refcount;
80 u8 power_ctl;
81}; 83};
82 84
83static inline struct mtk_dpi *mtk_dpi_from_encoder(struct drm_encoder *e) 85static inline struct mtk_dpi *mtk_dpi_from_encoder(struct drm_encoder *e)
@@ -90,11 +92,6 @@ enum mtk_dpi_polarity {
90 MTK_DPI_POLARITY_FALLING, 92 MTK_DPI_POLARITY_FALLING,
91}; 93};
92 94
93enum mtk_dpi_power_ctl {
94 DPI_POWER_START = BIT(0),
95 DPI_POWER_ENABLE = BIT(1),
96};
97
98struct mtk_dpi_polarities { 95struct mtk_dpi_polarities {
99 enum mtk_dpi_polarity de_pol; 96 enum mtk_dpi_polarity de_pol;
100 enum mtk_dpi_polarity ck_pol; 97 enum mtk_dpi_polarity ck_pol;
@@ -116,6 +113,12 @@ struct mtk_dpi_yc_limit {
116 u16 c_bottom; 113 u16 c_bottom;
117}; 114};
118 115
116struct mtk_dpi_conf {
117 unsigned int (*cal_factor)(int clock);
118 u32 reg_h_fre_con;
119 bool edge_sel_en;
120};
121
119static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) 122static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask)
120{ 123{
121 u32 tmp = readl(dpi->regs + offset) & ~mask; 124 u32 tmp = readl(dpi->regs + offset) & ~mask;
@@ -341,7 +344,13 @@ static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable)
341 344
342static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi) 345static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi)
343{ 346{
344 mtk_dpi_mask(dpi, DPI_H_FRE_CON, H_FRE_2N, H_FRE_2N); 347 mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N);
348}
349
350static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi)
351{
352 if (dpi->conf->edge_sel_en)
353 mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN);
345} 354}
346 355
347static void mtk_dpi_config_color_format(struct mtk_dpi *dpi, 356static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
@@ -367,40 +376,30 @@ static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
367 } 376 }
368} 377}
369 378
370static void mtk_dpi_power_off(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl) 379static void mtk_dpi_power_off(struct mtk_dpi *dpi)
371{ 380{
372 dpi->power_ctl &= ~pctl; 381 if (WARN_ON(dpi->refcount == 0))
373
374 if ((dpi->power_ctl & DPI_POWER_START) ||
375 (dpi->power_ctl & DPI_POWER_ENABLE))
376 return; 382 return;
377 383
378 if (!dpi->power_sta) 384 if (--dpi->refcount != 0)
379 return; 385 return;
380 386
381 mtk_dpi_disable(dpi); 387 mtk_dpi_disable(dpi);
382 clk_disable_unprepare(dpi->pixel_clk); 388 clk_disable_unprepare(dpi->pixel_clk);
383 clk_disable_unprepare(dpi->engine_clk); 389 clk_disable_unprepare(dpi->engine_clk);
384 dpi->power_sta = false;
385} 390}
386 391
387static int mtk_dpi_power_on(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl) 392static int mtk_dpi_power_on(struct mtk_dpi *dpi)
388{ 393{
389 int ret; 394 int ret;
390 395
391 dpi->power_ctl |= pctl; 396 if (++dpi->refcount != 1)
392
393 if (!(dpi->power_ctl & DPI_POWER_START) &&
394 !(dpi->power_ctl & DPI_POWER_ENABLE))
395 return 0;
396
397 if (dpi->power_sta)
398 return 0; 397 return 0;
399 398
400 ret = clk_prepare_enable(dpi->engine_clk); 399 ret = clk_prepare_enable(dpi->engine_clk);
401 if (ret) { 400 if (ret) {
402 dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret); 401 dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret);
403 goto err_eng; 402 goto err_refcount;
404 } 403 }
405 404
406 ret = clk_prepare_enable(dpi->pixel_clk); 405 ret = clk_prepare_enable(dpi->pixel_clk);
@@ -410,13 +409,12 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl)
410 } 409 }
411 410
412 mtk_dpi_enable(dpi); 411 mtk_dpi_enable(dpi);
413 dpi->power_sta = true;
414 return 0; 412 return 0;
415 413
416err_pixel: 414err_pixel:
417 clk_disable_unprepare(dpi->engine_clk); 415 clk_disable_unprepare(dpi->engine_clk);
418err_eng: 416err_refcount:
419 dpi->power_ctl &= ~pctl; 417 dpi->refcount--;
420 return ret; 418 return ret;
421} 419}
422 420
@@ -435,15 +433,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
435 unsigned int factor; 433 unsigned int factor;
436 434
437 /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */ 435 /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
438 436 factor = dpi->conf->cal_factor(mode->clock);
439 if (mode->clock <= 27000)
440 factor = 3 << 4;
441 else if (mode->clock <= 84000)
442 factor = 3 << 3;
443 else if (mode->clock <= 167000)
444 factor = 3 << 2;
445 else
446 factor = 3 << 1;
447 drm_display_mode_to_videomode(mode, &vm); 437 drm_display_mode_to_videomode(mode, &vm);
448 pll_rate = vm.pixelclock * factor; 438 pll_rate = vm.pixelclock * factor;
449 439
@@ -518,6 +508,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
518 mtk_dpi_config_yc_map(dpi, dpi->yc_map); 508 mtk_dpi_config_yc_map(dpi, dpi->yc_map);
519 mtk_dpi_config_color_format(dpi, dpi->color_format); 509 mtk_dpi_config_color_format(dpi, dpi->color_format);
520 mtk_dpi_config_2n_h_fre(dpi); 510 mtk_dpi_config_2n_h_fre(dpi);
511 mtk_dpi_config_disable_edge(dpi);
521 mtk_dpi_sw_reset(dpi, false); 512 mtk_dpi_sw_reset(dpi, false);
522 513
523 return 0; 514 return 0;
@@ -552,14 +543,14 @@ static void mtk_dpi_encoder_disable(struct drm_encoder *encoder)
552{ 543{
553 struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); 544 struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder);
554 545
555 mtk_dpi_power_off(dpi, DPI_POWER_ENABLE); 546 mtk_dpi_power_off(dpi);
556} 547}
557 548
558static void mtk_dpi_encoder_enable(struct drm_encoder *encoder) 549static void mtk_dpi_encoder_enable(struct drm_encoder *encoder)
559{ 550{
560 struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); 551 struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder);
561 552
562 mtk_dpi_power_on(dpi, DPI_POWER_ENABLE); 553 mtk_dpi_power_on(dpi);
563 mtk_dpi_set_display_mode(dpi, &dpi->mode); 554 mtk_dpi_set_display_mode(dpi, &dpi->mode);
564} 555}
565 556
@@ -582,14 +573,14 @@ static void mtk_dpi_start(struct mtk_ddp_comp *comp)
582{ 573{
583 struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp); 574 struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp);
584 575
585 mtk_dpi_power_on(dpi, DPI_POWER_START); 576 mtk_dpi_power_on(dpi);
586} 577}
587 578
588static void mtk_dpi_stop(struct mtk_ddp_comp *comp) 579static void mtk_dpi_stop(struct mtk_ddp_comp *comp)
589{ 580{
590 struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp); 581 struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp);
591 582
592 mtk_dpi_power_off(dpi, DPI_POWER_START); 583 mtk_dpi_power_off(dpi);
593} 584}
594 585
595static const struct mtk_ddp_comp_funcs mtk_dpi_funcs = { 586static const struct mtk_ddp_comp_funcs mtk_dpi_funcs = {
@@ -656,12 +647,46 @@ static const struct component_ops mtk_dpi_component_ops = {
656 .unbind = mtk_dpi_unbind, 647 .unbind = mtk_dpi_unbind,
657}; 648};
658 649
650static unsigned int mt8173_calculate_factor(int clock)
651{
652 if (clock <= 27000)
653 return 3 << 4;
654 else if (clock <= 84000)
655 return 3 << 3;
656 else if (clock <= 167000)
657 return 3 << 2;
658 else
659 return 3 << 1;
660}
661
662static unsigned int mt2701_calculate_factor(int clock)
663{
664 if (clock <= 64000)
665 return 16;
666 else if (clock <= 128000)
667 return 8;
668 else if (clock <= 256000)
669 return 4;
670 else
671 return 2;
672}
673
674static const struct mtk_dpi_conf mt8173_conf = {
675 .cal_factor = mt8173_calculate_factor,
676 .reg_h_fre_con = 0xe0,
677};
678
679static const struct mtk_dpi_conf mt2701_conf = {
680 .cal_factor = mt2701_calculate_factor,
681 .reg_h_fre_con = 0xb0,
682 .edge_sel_en = true,
683};
684
659static int mtk_dpi_probe(struct platform_device *pdev) 685static int mtk_dpi_probe(struct platform_device *pdev)
660{ 686{
661 struct device *dev = &pdev->dev; 687 struct device *dev = &pdev->dev;
662 struct mtk_dpi *dpi; 688 struct mtk_dpi *dpi;
663 struct resource *mem; 689 struct resource *mem;
664 struct device_node *bridge_node;
665 int comp_id; 690 int comp_id;
666 int ret; 691 int ret;
667 692
@@ -670,6 +695,7 @@ static int mtk_dpi_probe(struct platform_device *pdev)
670 return -ENOMEM; 695 return -ENOMEM;
671 696
672 dpi->dev = dev; 697 dpi->dev = dev;
698 dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev);
673 699
674 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 700 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
675 dpi->regs = devm_ioremap_resource(dev, mem); 701 dpi->regs = devm_ioremap_resource(dev, mem);
@@ -706,16 +732,12 @@ static int mtk_dpi_probe(struct platform_device *pdev)
706 return -EINVAL; 732 return -EINVAL;
707 } 733 }
708 734
709 bridge_node = of_graph_get_remote_node(dev->of_node, 0, 0); 735 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
710 if (!bridge_node) 736 NULL, &dpi->bridge);
711 return -ENODEV; 737 if (ret)
712 738 return ret;
713 dev_info(dev, "Found bridge node: %pOF\n", bridge_node);
714 739
715 dpi->bridge = of_drm_find_bridge(bridge_node); 740 dev_info(dev, "Found bridge node: %pOF\n", dpi->bridge->of_node);
716 of_node_put(bridge_node);
717 if (!dpi->bridge)
718 return -EPROBE_DEFER;
719 741
720 comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI); 742 comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
721 if (comp_id < 0) { 743 if (comp_id < 0) {
@@ -749,8 +771,13 @@ static int mtk_dpi_remove(struct platform_device *pdev)
749} 771}
750 772
751static const struct of_device_id mtk_dpi_of_ids[] = { 773static const struct of_device_id mtk_dpi_of_ids[] = {
752 { .compatible = "mediatek,mt8173-dpi", }, 774 { .compatible = "mediatek,mt2701-dpi",
753 {} 775 .data = &mt2701_conf,
776 },
777 { .compatible = "mediatek,mt8173-dpi",
778 .data = &mt8173_conf,
779 },
780 { },
754}; 781};
755 782
756struct platform_driver mtk_dpi_driver = { 783struct platform_driver mtk_dpi_driver = {
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
index 4b6ad4751a31..d9db8c4cacd7 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
+++ b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
@@ -223,6 +223,6 @@
223#define ESAV_CODE2 (0xFFF << 0) 223#define ESAV_CODE2 (0xFFF << 0)
224#define ESAV_CODE3_MSB BIT(16) 224#define ESAV_CODE3_MSB BIT(16)
225 225
226#define DPI_H_FRE_CON 0xE0 226#define EDGE_SEL_EN BIT(5)
227#define H_FRE_2N BIT(25) 227#define H_FRE_2N BIT(25)
228#endif /* __MTK_DPI_REGS_H */ 228#endif /* __MTK_DPI_REGS_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 546b3e3b300b..579ce28d801d 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -39,6 +39,7 @@
39#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030 39#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030
40#define DISP_REG_CONFIG_OUT_SEL 0x04c 40#define DISP_REG_CONFIG_OUT_SEL 0x04c
41#define DISP_REG_CONFIG_DSI_SEL 0x050 41#define DISP_REG_CONFIG_DSI_SEL 0x050
42#define DISP_REG_CONFIG_DPI_SEL 0x064
42 43
43#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n)) 44#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
44#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n)) 45#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
@@ -136,7 +137,10 @@
136 137
137#define OVL_MOUT_EN_RDMA 0x1 138#define OVL_MOUT_EN_RDMA 0x1
138#define BLS_TO_DSI_RDMA1_TO_DPI1 0x8 139#define BLS_TO_DSI_RDMA1_TO_DPI1 0x8
140#define BLS_TO_DPI_RDMA1_TO_DSI 0x2
139#define DSI_SEL_IN_BLS 0x0 141#define DSI_SEL_IN_BLS 0x0
142#define DPI_SEL_IN_BLS 0x0
143#define DSI_SEL_IN_RDMA 0x1
140 144
141struct mtk_disp_mutex { 145struct mtk_disp_mutex {
142 int id; 146 int id;
@@ -339,9 +343,17 @@ static void mtk_ddp_sout_sel(void __iomem *config_regs,
339 enum mtk_ddp_comp_id cur, 343 enum mtk_ddp_comp_id cur,
340 enum mtk_ddp_comp_id next) 344 enum mtk_ddp_comp_id next)
341{ 345{
342 if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) 346 if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
343 writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1, 347 writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
344 config_regs + DISP_REG_CONFIG_OUT_SEL); 348 config_regs + DISP_REG_CONFIG_OUT_SEL);
349 } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DPI0) {
350 writel_relaxed(BLS_TO_DPI_RDMA1_TO_DSI,
351 config_regs + DISP_REG_CONFIG_OUT_SEL);
352 writel_relaxed(DSI_SEL_IN_RDMA,
353 config_regs + DISP_REG_CONFIG_DSI_SEL);
354 writel_relaxed(DPI_SEL_IN_BLS,
355 config_regs + DISP_REG_CONFIG_DPI_SEL);
356 }
345} 357}
346 358
347void mtk_ddp_add_comp_to_path(void __iomem *config_regs, 359void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index ff974d82a4a6..54ca794db3e9 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -294,7 +294,7 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
294 comp->irq = of_irq_get(node, 0); 294 comp->irq = of_irq_get(node, 0);
295 comp->clk = of_clk_get(node, 0); 295 comp->clk = of_clk_get(node, 0);
296 if (IS_ERR(comp->clk)) 296 if (IS_ERR(comp->clk))
297 comp->clk = NULL; 297 return PTR_ERR(comp->clk);
298 298
299 /* Only DMA capable components need the LARB property */ 299 /* Only DMA capable components need the LARB property */
300 comp->larb_dev = NULL; 300 comp->larb_dev = NULL;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 47ec604289b7..6422e99952fe 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -424,6 +424,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
424 .data = (void *)MTK_DSI }, 424 .data = (void *)MTK_DSI },
425 { .compatible = "mediatek,mt8173-dsi", 425 { .compatible = "mediatek,mt8173-dsi",
426 .data = (void *)MTK_DSI }, 426 .data = (void *)MTK_DSI },
427 { .compatible = "mediatek,mt2701-dpi",
428 .data = (void *)MTK_DPI },
427 { .compatible = "mediatek,mt8173-dpi", 429 { .compatible = "mediatek,mt8173-dpi",
428 .data = (void *)MTK_DPI }, 430 .data = (void *)MTK_DPI },
429 { .compatible = "mediatek,mt2701-disp-mutex", 431 { .compatible = "mediatek,mt2701-disp-mutex",
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 2d45d1dd9554..11e3644da79a 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -233,6 +233,7 @@ static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black)
233static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable) 233static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable)
234{ 234{
235 struct arm_smccc_res res; 235 struct arm_smccc_res res;
236 struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(hdmi->phy);
236 237
237 /* 238 /*
238 * MT8173 HDMI hardware has an output control bit to enable/disable HDMI 239 * MT8173 HDMI hardware has an output control bit to enable/disable HDMI
@@ -240,8 +241,13 @@ static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable)
240 * The ARM trusted firmware provides an API for the HDMI driver to set 241 * The ARM trusted firmware provides an API for the HDMI driver to set
241 * this control bit to enable HDMI output in supervisor mode. 242 * this control bit to enable HDMI output in supervisor mode.
242 */ 243 */
243 arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, 0x80000000, 244 if (hdmi_phy->conf && hdmi_phy->conf->tz_disabled)
244 0, 0, 0, 0, 0, &res); 245 regmap_update_bits(hdmi->sys_regmap,
246 hdmi->sys_offset + HDMI_SYS_CFG20,
247 0x80008005, enable ? 0x80000005 : 0x8000);
248 else
249 arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904,
250 0x80000000, 0, 0, 0, 0, 0, &res);
245 251
246 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20, 252 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
247 HDMI_PCLK_FREE_RUN, enable ? HDMI_PCLK_FREE_RUN : 0); 253 HDMI_PCLK_FREE_RUN, enable ? HDMI_PCLK_FREE_RUN : 0);
@@ -1575,6 +1581,11 @@ static int mtk_hdmi_audio_hw_params(struct device *dev, void *data,
1575 hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; 1581 hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT;
1576 hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS; 1582 hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS;
1577 break; 1583 break;
1584 case HDMI_SPDIF:
1585 hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
1586 hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16;
1587 hdmi_params.aud_input_type = HDMI_AUD_INPUT_SPDIF;
1588 break;
1578 default: 1589 default:
1579 dev_err(hdmi->dev, "%s: Invalid DAI format %d\n", __func__, 1590 dev_err(hdmi->dev, "%s: Invalid DAI format %d\n", __func__,
1580 daifmt->fmt); 1591 daifmt->fmt);
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.h b/drivers/gpu/drm/mediatek/mtk_hdmi.h
index 6371b3de1ff6..3e9fb8d19802 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.h
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.h
@@ -13,11 +13,11 @@
13 */ 13 */
14#ifndef _MTK_HDMI_CTRL_H 14#ifndef _MTK_HDMI_CTRL_H
15#define _MTK_HDMI_CTRL_H 15#define _MTK_HDMI_CTRL_H
16#include "mtk_hdmi_phy.h"
16 17
17struct platform_driver; 18struct platform_driver;
18 19
19extern struct platform_driver mtk_cec_driver; 20extern struct platform_driver mtk_cec_driver;
20extern struct platform_driver mtk_hdmi_ddc_driver; 21extern struct platform_driver mtk_hdmi_ddc_driver;
21extern struct platform_driver mtk_hdmi_phy_driver;
22 22
23#endif /* _MTK_HDMI_CTRL_H */ 23#endif /* _MTK_HDMI_CTRL_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
new file mode 100644
index 000000000000..4ef9c57ffd44
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
@@ -0,0 +1,235 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018 MediaTek Inc.
4 * Author: Jie Qiu <jie.qiu@mediatek.com>
5 */
6
7#include "mtk_hdmi_phy.h"
8
9static int mtk_hdmi_phy_power_on(struct phy *phy);
10static int mtk_hdmi_phy_power_off(struct phy *phy);
11
12static const struct phy_ops mtk_hdmi_phy_dev_ops = {
13 .power_on = mtk_hdmi_phy_power_on,
14 .power_off = mtk_hdmi_phy_power_off,
15 .owner = THIS_MODULE,
16};
17
18long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
19 unsigned long *parent_rate)
20{
21 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
22
23 hdmi_phy->pll_rate = rate;
24 if (rate <= 74250000)
25 *parent_rate = rate;
26 else
27 *parent_rate = rate / 2;
28
29 return rate;
30}
31
32unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
33 unsigned long parent_rate)
34{
35 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
36
37 return hdmi_phy->pll_rate;
38}
39
40void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
41 u32 bits)
42{
43 void __iomem *reg = hdmi_phy->regs + offset;
44 u32 tmp;
45
46 tmp = readl(reg);
47 tmp &= ~bits;
48 writel(tmp, reg);
49}
50
51void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
52 u32 bits)
53{
54 void __iomem *reg = hdmi_phy->regs + offset;
55 u32 tmp;
56
57 tmp = readl(reg);
58 tmp |= bits;
59 writel(tmp, reg);
60}
61
62void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
63 u32 val, u32 mask)
64{
65 void __iomem *reg = hdmi_phy->regs + offset;
66 u32 tmp;
67
68 tmp = readl(reg);
69 tmp = (tmp & ~mask) | (val & mask);
70 writel(tmp, reg);
71}
72
73inline struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw)
74{
75 return container_of(hw, struct mtk_hdmi_phy, pll_hw);
76}
77
78static int mtk_hdmi_phy_power_on(struct phy *phy)
79{
80 struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
81 int ret;
82
83 ret = clk_prepare_enable(hdmi_phy->pll);
84 if (ret < 0)
85 return ret;
86
87 hdmi_phy->conf->hdmi_phy_enable_tmds(hdmi_phy);
88 return 0;
89}
90
91static int mtk_hdmi_phy_power_off(struct phy *phy)
92{
93 struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
94
95 hdmi_phy->conf->hdmi_phy_disable_tmds(hdmi_phy);
96 clk_disable_unprepare(hdmi_phy->pll);
97
98 return 0;
99}
100
101static const struct phy_ops *
102mtk_hdmi_phy_dev_get_ops(const struct mtk_hdmi_phy *hdmi_phy)
103{
104 if (hdmi_phy && hdmi_phy->conf &&
105 hdmi_phy->conf->hdmi_phy_enable_tmds &&
106 hdmi_phy->conf->hdmi_phy_disable_tmds)
107 return &mtk_hdmi_phy_dev_ops;
108
109 dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n");
110 return NULL;
111}
112
113static void mtk_hdmi_phy_clk_get_ops(struct mtk_hdmi_phy *hdmi_phy,
114 const struct clk_ops **ops)
115{
116 if (hdmi_phy && hdmi_phy->conf && hdmi_phy->conf->hdmi_phy_clk_ops)
117 *ops = hdmi_phy->conf->hdmi_phy_clk_ops;
118 else
119 dev_err(hdmi_phy->dev, "Failed to get clk ops of phy\n");
120}
121
122static int mtk_hdmi_phy_probe(struct platform_device *pdev)
123{
124 struct device *dev = &pdev->dev;
125 struct mtk_hdmi_phy *hdmi_phy;
126 struct resource *mem;
127 struct clk *ref_clk;
128 const char *ref_clk_name;
129 struct clk_init_data clk_init = {
130 .num_parents = 1,
131 .parent_names = (const char * const *)&ref_clk_name,
132 .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
133 };
134
135 struct phy *phy;
136 struct phy_provider *phy_provider;
137 int ret;
138
139 hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
140 if (!hdmi_phy)
141 return -ENOMEM;
142
143 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
144 hdmi_phy->regs = devm_ioremap_resource(dev, mem);
145 if (IS_ERR(hdmi_phy->regs)) {
146 ret = PTR_ERR(hdmi_phy->regs);
147 dev_err(dev, "Failed to get memory resource: %d\n", ret);
148 return ret;
149 }
150
151 ref_clk = devm_clk_get(dev, "pll_ref");
152 if (IS_ERR(ref_clk)) {
153 ret = PTR_ERR(ref_clk);
154 dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n",
155 ret);
156 return ret;
157 }
158 ref_clk_name = __clk_get_name(ref_clk);
159
160 ret = of_property_read_string(dev->of_node, "clock-output-names",
161 &clk_init.name);
162 if (ret < 0) {
163 dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
164 return ret;
165 }
166
167 hdmi_phy->dev = dev;
168 hdmi_phy->conf =
169 (struct mtk_hdmi_phy_conf *)of_device_get_match_data(dev);
170 mtk_hdmi_phy_clk_get_ops(hdmi_phy, &clk_init.ops);
171 hdmi_phy->pll_hw.init = &clk_init;
172 hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
173 if (IS_ERR(hdmi_phy->pll)) {
174 ret = PTR_ERR(hdmi_phy->pll);
175 dev_err(dev, "Failed to register PLL: %d\n", ret);
176 return ret;
177 }
178
179 ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
180 &hdmi_phy->ibias);
181 if (ret < 0) {
182 dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
183 return ret;
184 }
185
186 ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
187 &hdmi_phy->ibias_up);
188 if (ret < 0) {
189 dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
190 return ret;
191 }
192
193 dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
194 hdmi_phy->drv_imp_clk = 0x30;
195 hdmi_phy->drv_imp_d2 = 0x30;
196 hdmi_phy->drv_imp_d1 = 0x30;
197 hdmi_phy->drv_imp_d0 = 0x30;
198
199 phy = devm_phy_create(dev, NULL, mtk_hdmi_phy_dev_get_ops(hdmi_phy));
200 if (IS_ERR(phy)) {
201 dev_err(dev, "Failed to create HDMI PHY\n");
202 return PTR_ERR(phy);
203 }
204 phy_set_drvdata(phy, hdmi_phy);
205
206 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
207 if (IS_ERR(phy_provider)) {
208 dev_err(dev, "Failed to register HDMI PHY\n");
209 return PTR_ERR(phy_provider);
210 }
211
212 return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
213 hdmi_phy->pll);
214}
215
216static const struct of_device_id mtk_hdmi_phy_match[] = {
217 { .compatible = "mediatek,mt2701-hdmi-phy",
218 .data = &mtk_hdmi_phy_2701_conf,
219 },
220 { .compatible = "mediatek,mt8173-hdmi-phy",
221 .data = &mtk_hdmi_phy_8173_conf,
222 },
223 {},
224};
225
226struct platform_driver mtk_hdmi_phy_driver = {
227 .probe = mtk_hdmi_phy_probe,
228 .driver = {
229 .name = "mediatek-hdmi-phy",
230 .of_match_table = mtk_hdmi_phy_match,
231 },
232};
233
234MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
235MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h
new file mode 100644
index 000000000000..f39b1fc66612
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h
@@ -0,0 +1,60 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2018 MediaTek Inc.
4 * Author: Chunhui Dai <chunhui.dai@mediatek.com>
5 */
6
7#ifndef _MTK_HDMI_PHY_H
8#define _MTK_HDMI_PHY_H
9#include <linux/clk.h>
10#include <linux/clk-provider.h>
11#include <linux/delay.h>
12#include <linux/io.h>
13#include <linux/mfd/syscon.h>
14#include <linux/module.h>
15#include <linux/of_device.h>
16#include <linux/phy/phy.h>
17#include <linux/platform_device.h>
18#include <linux/types.h>
19
20struct mtk_hdmi_phy;
21
22struct mtk_hdmi_phy_conf {
23 bool tz_disabled;
24 const struct clk_ops *hdmi_phy_clk_ops;
25 void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
26 void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
27};
28
29struct mtk_hdmi_phy {
30 void __iomem *regs;
31 struct device *dev;
32 struct mtk_hdmi_phy_conf *conf;
33 struct clk *pll;
34 struct clk_hw pll_hw;
35 unsigned long pll_rate;
36 unsigned char drv_imp_clk;
37 unsigned char drv_imp_d2;
38 unsigned char drv_imp_d1;
39 unsigned char drv_imp_d0;
40 unsigned int ibias;
41 unsigned int ibias_up;
42};
43
44void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
45 u32 bits);
46void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
47 u32 bits);
48void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
49 u32 val, u32 mask);
50struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw);
51long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
52 unsigned long *parent_rate);
53unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
54 unsigned long parent_rate);
55
56extern struct platform_driver mtk_hdmi_phy_driver;
57extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf;
58extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf;
59
60#endif /* _MTK_HDMI_PHY_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c
new file mode 100644
index 000000000000..fcc42dc6ea7f
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c
@@ -0,0 +1,212 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018 MediaTek Inc.
4 * Author: Chunhui Dai <chunhui.dai@mediatek.com>
5 */
6
7#include "mtk_hdmi_phy.h"
8
9#define HDMI_CON0 0x00
10#define RG_HDMITX_DRV_IBIAS 0
11#define RG_HDMITX_DRV_IBIAS_MASK (0x3f << 0)
12#define RG_HDMITX_EN_SER 12
13#define RG_HDMITX_EN_SER_MASK (0x0f << 12)
14#define RG_HDMITX_EN_SLDO 16
15#define RG_HDMITX_EN_SLDO_MASK (0x0f << 16)
16#define RG_HDMITX_EN_PRED 20
17#define RG_HDMITX_EN_PRED_MASK (0x0f << 20)
18#define RG_HDMITX_EN_IMP 24
19#define RG_HDMITX_EN_IMP_MASK (0x0f << 24)
20#define RG_HDMITX_EN_DRV 28
21#define RG_HDMITX_EN_DRV_MASK (0x0f << 28)
22
23#define HDMI_CON1 0x04
24#define RG_HDMITX_PRED_IBIAS 18
25#define RG_HDMITX_PRED_IBIAS_MASK (0x0f << 18)
26#define RG_HDMITX_PRED_IMP (0x01 << 22)
27#define RG_HDMITX_DRV_IMP 26
28#define RG_HDMITX_DRV_IMP_MASK (0x3f << 26)
29
30#define HDMI_CON2 0x08
31#define RG_HDMITX_EN_TX_CKLDO (0x01 << 0)
32#define RG_HDMITX_EN_TX_POSDIV (0x01 << 1)
33#define RG_HDMITX_TX_POSDIV 3
34#define RG_HDMITX_TX_POSDIV_MASK (0x03 << 3)
35#define RG_HDMITX_EN_MBIAS (0x01 << 6)
36#define RG_HDMITX_MBIAS_LPF_EN (0x01 << 7)
37
38#define HDMI_CON4 0x10
39#define RG_HDMITX_RESERVE_MASK (0xffffffff << 0)
40
41#define HDMI_CON6 0x18
42#define RG_HTPLL_BR 0
43#define RG_HTPLL_BR_MASK (0x03 << 0)
44#define RG_HTPLL_BC 2
45#define RG_HTPLL_BC_MASK (0x03 << 2)
46#define RG_HTPLL_BP 4
47#define RG_HTPLL_BP_MASK (0x0f << 4)
48#define RG_HTPLL_IR 8
49#define RG_HTPLL_IR_MASK (0x0f << 8)
50#define RG_HTPLL_IC 12
51#define RG_HTPLL_IC_MASK (0x0f << 12)
52#define RG_HTPLL_POSDIV 16
53#define RG_HTPLL_POSDIV_MASK (0x03 << 16)
54#define RG_HTPLL_PREDIV 18
55#define RG_HTPLL_PREDIV_MASK (0x03 << 18)
56#define RG_HTPLL_FBKSEL 20
57#define RG_HTPLL_FBKSEL_MASK (0x03 << 20)
58#define RG_HTPLL_RLH_EN (0x01 << 22)
59#define RG_HTPLL_FBKDIV 24
60#define RG_HTPLL_FBKDIV_MASK (0x7f << 24)
61#define RG_HTPLL_EN (0x01 << 31)
62
63#define HDMI_CON7 0x1c
64#define RG_HTPLL_AUTOK_EN (0x01 << 23)
65#define RG_HTPLL_DIVEN 28
66#define RG_HTPLL_DIVEN_MASK (0x07 << 28)
67
68static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
69{
70 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
71
72 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
73 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
74 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
75 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
76 usleep_range(80, 100);
77 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
78 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
79 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
80 usleep_range(80, 100);
81 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
82 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
83 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
84 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
85 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
86 usleep_range(80, 100);
87 return 0;
88}
89
90static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
91{
92 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
93
94 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
95 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
96 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
97 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
98 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
99 usleep_range(80, 100);
100 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
101 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
102 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
103 usleep_range(80, 100);
104 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
105 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
106 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
107 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
108 usleep_range(80, 100);
109}
110
111static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
112 unsigned long parent_rate)
113{
114 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
115 u32 pos_div;
116
117 if (rate <= 64000000)
118 pos_div = 3;
119 else if (rate <= 12800000)
120 pos_div = 1;
121 else
122 pos_div = 1;
123
124 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_PREDIV_MASK);
125 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
126 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IC),
127 RG_HTPLL_IC_MASK);
128 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IR),
129 RG_HTPLL_IR_MASK);
130 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON2, (pos_div << RG_HDMITX_TX_POSDIV),
131 RG_HDMITX_TX_POSDIV_MASK);
132 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (1 << RG_HTPLL_FBKSEL),
133 RG_HTPLL_FBKSEL_MASK);
134 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (19 << RG_HTPLL_FBKDIV),
135 RG_HTPLL_FBKDIV_MASK);
136 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON7, (0x2 << RG_HTPLL_DIVEN),
137 RG_HTPLL_DIVEN_MASK);
138 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0xc << RG_HTPLL_BP),
139 RG_HTPLL_BP_MASK);
140 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x2 << RG_HTPLL_BC),
141 RG_HTPLL_BC_MASK);
142 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_BR),
143 RG_HTPLL_BR_MASK);
144
145 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PRED_IMP);
146 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x3 << RG_HDMITX_PRED_IBIAS),
147 RG_HDMITX_PRED_IBIAS_MASK);
148 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_IMP_MASK);
149 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x28 << RG_HDMITX_DRV_IMP),
150 RG_HDMITX_DRV_IMP_MASK);
151 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4, 0x28, RG_HDMITX_RESERVE_MASK);
152 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0, (0xa << RG_HDMITX_DRV_IBIAS),
153 RG_HDMITX_DRV_IBIAS_MASK);
154 return 0;
155}
156
157static const struct clk_ops mtk_hdmi_phy_pll_ops = {
158 .prepare = mtk_hdmi_pll_prepare,
159 .unprepare = mtk_hdmi_pll_unprepare,
160 .set_rate = mtk_hdmi_pll_set_rate,
161 .round_rate = mtk_hdmi_pll_round_rate,
162 .recalc_rate = mtk_hdmi_pll_recalc_rate,
163};
164
165static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
166{
167 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
168 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
169 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
170 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
171 usleep_range(80, 100);
172 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
173 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
174 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
175 usleep_range(80, 100);
176 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
177 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
178 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
179 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
180 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
181 usleep_range(80, 100);
182}
183
184static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
185{
186 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
187 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
188 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
189 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
190 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
191 usleep_range(80, 100);
192 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
193 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
194 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
195 usleep_range(80, 100);
196 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
197 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
198 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
199 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
200 usleep_range(80, 100);
201}
202
203struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = {
204 .tz_disabled = true,
205 .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
206 .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
207 .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
208};
209
210MODULE_AUTHOR("Chunhui Dai <chunhui.dai@mediatek.com>");
211MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
212MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
index 51cb9cfb6646..ed5916b27658 100644
--- a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
+++ b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
@@ -12,15 +12,7 @@
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 */ 13 */
14 14
15#include <linux/clk.h> 15#include "mtk_hdmi_phy.h"
16#include <linux/clk-provider.h>
17#include <linux/delay.h>
18#include <linux/io.h>
19#include <linux/mfd/syscon.h>
20#include <linux/module.h>
21#include <linux/phy/phy.h>
22#include <linux/platform_device.h>
23#include <linux/types.h>
24 16
25#define HDMI_CON0 0x00 17#define HDMI_CON0 0x00
26#define RG_HDMITX_PLL_EN BIT(31) 18#define RG_HDMITX_PLL_EN BIT(31)
@@ -123,20 +115,6 @@
123#define RGS_HDMITX_5T1_EDG (0xf << 4) 115#define RGS_HDMITX_5T1_EDG (0xf << 4)
124#define RGS_HDMITX_PLUG_TST BIT(0) 116#define RGS_HDMITX_PLUG_TST BIT(0)
125 117
126struct mtk_hdmi_phy {
127 void __iomem *regs;
128 struct device *dev;
129 struct clk *pll;
130 struct clk_hw pll_hw;
131 unsigned long pll_rate;
132 u8 drv_imp_clk;
133 u8 drv_imp_d2;
134 u8 drv_imp_d1;
135 u8 drv_imp_d0;
136 u32 ibias;
137 u32 ibias_up;
138};
139
140static const u8 PREDIV[3][4] = { 118static const u8 PREDIV[3][4] = {
141 {0x0, 0x0, 0x0, 0x0}, /* 27Mhz */ 119 {0x0, 0x0, 0x0, 0x0}, /* 27Mhz */
142 {0x1, 0x1, 0x1, 0x1}, /* 74Mhz */ 120 {0x1, 0x1, 0x1, 0x1}, /* 74Mhz */
@@ -185,44 +163,6 @@ static const u8 HTPLLBR[3][4] = {
185 {0x1, 0x2, 0x2, 0x1} /* 148Mhz */ 163 {0x1, 0x2, 0x2, 0x1} /* 148Mhz */
186}; 164};
187 165
188static void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
189 u32 bits)
190{
191 void __iomem *reg = hdmi_phy->regs + offset;
192 u32 tmp;
193
194 tmp = readl(reg);
195 tmp &= ~bits;
196 writel(tmp, reg);
197}
198
199static void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
200 u32 bits)
201{
202 void __iomem *reg = hdmi_phy->regs + offset;
203 u32 tmp;
204
205 tmp = readl(reg);
206 tmp |= bits;
207 writel(tmp, reg);
208}
209
210static void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
211 u32 val, u32 mask)
212{
213 void __iomem *reg = hdmi_phy->regs + offset;
214 u32 tmp;
215
216 tmp = readl(reg);
217 tmp = (tmp & ~mask) | (val & mask);
218 writel(tmp, reg);
219}
220
221static inline struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw)
222{
223 return container_of(hw, struct mtk_hdmi_phy, pll_hw);
224}
225
226static int mtk_hdmi_pll_prepare(struct clk_hw *hw) 166static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
227{ 167{
228 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw); 168 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
@@ -345,29 +285,7 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
345 return 0; 285 return 0;
346} 286}
347 287
348static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate, 288static const struct clk_ops mtk_hdmi_phy_pll_ops = {
349 unsigned long *parent_rate)
350{
351 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
352
353 hdmi_phy->pll_rate = rate;
354 if (rate <= 74250000)
355 *parent_rate = rate;
356 else
357 *parent_rate = rate / 2;
358
359 return rate;
360}
361
362static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
363 unsigned long parent_rate)
364{
365 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
366
367 return hdmi_phy->pll_rate;
368}
369
370static const struct clk_ops mtk_hdmi_pll_ops = {
371 .prepare = mtk_hdmi_pll_prepare, 289 .prepare = mtk_hdmi_pll_prepare,
372 .unprepare = mtk_hdmi_pll_unprepare, 290 .unprepare = mtk_hdmi_pll_unprepare,
373 .set_rate = mtk_hdmi_pll_set_rate, 291 .set_rate = mtk_hdmi_pll_set_rate,
@@ -390,142 +308,10 @@ static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
390 RG_HDMITX_SER_EN); 308 RG_HDMITX_SER_EN);
391} 309}
392 310
393static int mtk_hdmi_phy_power_on(struct phy *phy) 311struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf = {
394{ 312 .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
395 struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy); 313 .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
396 int ret; 314 .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
397
398 ret = clk_prepare_enable(hdmi_phy->pll);
399 if (ret < 0)
400 return ret;
401
402 mtk_hdmi_phy_enable_tmds(hdmi_phy);
403
404 return 0;
405}
406
407static int mtk_hdmi_phy_power_off(struct phy *phy)
408{
409 struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
410
411 mtk_hdmi_phy_disable_tmds(hdmi_phy);
412 clk_disable_unprepare(hdmi_phy->pll);
413
414 return 0;
415}
416
417static const struct phy_ops mtk_hdmi_phy_ops = {
418 .power_on = mtk_hdmi_phy_power_on,
419 .power_off = mtk_hdmi_phy_power_off,
420 .owner = THIS_MODULE,
421};
422
423static int mtk_hdmi_phy_probe(struct platform_device *pdev)
424{
425 struct device *dev = &pdev->dev;
426 struct mtk_hdmi_phy *hdmi_phy;
427 struct resource *mem;
428 struct clk *ref_clk;
429 const char *ref_clk_name;
430 struct clk_init_data clk_init = {
431 .ops = &mtk_hdmi_pll_ops,
432 .num_parents = 1,
433 .parent_names = (const char * const *)&ref_clk_name,
434 .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
435 };
436 struct phy *phy;
437 struct phy_provider *phy_provider;
438 int ret;
439
440 hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
441 if (!hdmi_phy)
442 return -ENOMEM;
443
444 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
445 hdmi_phy->regs = devm_ioremap_resource(dev, mem);
446 if (IS_ERR(hdmi_phy->regs)) {
447 ret = PTR_ERR(hdmi_phy->regs);
448 dev_err(dev, "Failed to get memory resource: %d\n", ret);
449 return ret;
450 }
451
452 ref_clk = devm_clk_get(dev, "pll_ref");
453 if (IS_ERR(ref_clk)) {
454 ret = PTR_ERR(ref_clk);
455 dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n",
456 ret);
457 return ret;
458 }
459 ref_clk_name = __clk_get_name(ref_clk);
460
461 ret = of_property_read_string(dev->of_node, "clock-output-names",
462 &clk_init.name);
463 if (ret < 0) {
464 dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
465 return ret;
466 }
467
468 hdmi_phy->pll_hw.init = &clk_init;
469 hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
470 if (IS_ERR(hdmi_phy->pll)) {
471 ret = PTR_ERR(hdmi_phy->pll);
472 dev_err(dev, "Failed to register PLL: %d\n", ret);
473 return ret;
474 }
475
476 ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
477 &hdmi_phy->ibias);
478 if (ret < 0) {
479 dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
480 return ret;
481 }
482
483 ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
484 &hdmi_phy->ibias_up);
485 if (ret < 0) {
486 dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
487 return ret;
488 }
489
490 dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
491 hdmi_phy->drv_imp_clk = 0x30;
492 hdmi_phy->drv_imp_d2 = 0x30;
493 hdmi_phy->drv_imp_d1 = 0x30;
494 hdmi_phy->drv_imp_d0 = 0x30;
495
496 phy = devm_phy_create(dev, NULL, &mtk_hdmi_phy_ops);
497 if (IS_ERR(phy)) {
498 dev_err(dev, "Failed to create HDMI PHY\n");
499 return PTR_ERR(phy);
500 }
501 phy_set_drvdata(phy, hdmi_phy);
502
503 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
504 if (IS_ERR(phy_provider))
505 return PTR_ERR(phy_provider);
506
507 hdmi_phy->dev = dev;
508 return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
509 hdmi_phy->pll);
510}
511
512static int mtk_hdmi_phy_remove(struct platform_device *pdev)
513{
514 return 0;
515}
516
517static const struct of_device_id mtk_hdmi_phy_match[] = {
518 { .compatible = "mediatek,mt8173-hdmi-phy", },
519 {},
520};
521
522struct platform_driver mtk_hdmi_phy_driver = {
523 .probe = mtk_hdmi_phy_probe,
524 .remove = mtk_hdmi_phy_remove,
525 .driver = {
526 .name = "mediatek-hdmi-phy",
527 .of_match_table = mtk_hdmi_phy_match,
528 },
529}; 315};
530 316
531MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>"); 317MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>");