1 /*
2 * Copyright (c) 2023 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 #include "hpm_panel.h"
8 #include "hpm_pixelmux_drv.h"
9 #include "hpm_lvb_drv.h"
10
lvds_panel_lvb_init(hpm_panel_t * panel)11 static void lvds_panel_lvb_init(hpm_panel_t *panel)
12 {
13 LVB_Type *lvb_base = panel->hw_if.video.lvds.lvb_base;
14 lvb_config_t lvb_config;
15 lvb_get_default_config(&lvb_config);
16
17 lvb_config.split_mode_en = true;
18 lvb_config.txclk_shift = lvb_txclk_shift_1100011;
19 lvb_init(lvb_base, &lvb_config);
20
21 lvb_ch_config_t lvb_ch_cfg;
22 lvb_ch_cfg.map = lvb_ch_mapping_vesa;
23
24 if (panel->hw_if.video.lvds.channel_di_index == 0)
25 lvb_ch_cfg.data_src = lvb_ch_data_source_di0;
26 else
27 lvb_ch_cfg.data_src = lvb_ch_data_source_di1;
28
29 lvb_ch_config(lvb_base, lvb_ch_num_0, &lvb_ch_cfg);
30 lvb_ch_config(lvb_base, lvb_ch_num_1, &lvb_ch_cfg);
31
32 lvb_ch_enable(lvb_base, lvb_ch_num_0);
33 lvb_ch_enable(lvb_base, lvb_ch_num_1);
34 }
35
lvds_panel_phy_init(hpm_panel_t * panel)36 static void lvds_panel_phy_init(hpm_panel_t *panel)
37 {
38 LVB_Type *lvb_base = panel->hw_if.video.lvds.lvb_base;
39 lvds_phy_clk_param_t param;
40 uint32_t pixel_clk = panel->hw_if.lcdc_pixel_clk_khz * 1000;
41 pixelmux_lvds_phy_calc_pll_cfg(pixel_clk, true, ¶m);
42 pixelmux_config_lvds_tx_phy0_clk(¶m.reg);
43 pixelmux_config_lvds_tx_phy1_clk(¶m.reg);
44
45 lvb_lvds_phy_lane_config_t lvds_lane_cfg;
46 lvb_lvds_phy_lane_get_default_config(&lvds_lane_cfg);
47 lvds_lane_cfg.fvco_div4 = param.reg.data_rate_div4;
48 lvb_lvds_phy_lane_init(lvb_base, lvb_lvds_lane_idx_lvds0_tx0, &lvds_lane_cfg);
49 lvb_lvds_phy_lane_init(lvb_base, lvb_lvds_lane_idx_lvds0_tx1, &lvds_lane_cfg);
50 lvb_lvds_phy_lane_init(lvb_base, lvb_lvds_lane_idx_lvds0_tx2, &lvds_lane_cfg);
51 lvb_lvds_phy_lane_init(lvb_base, lvb_lvds_lane_idx_lvds0_tx3, &lvds_lane_cfg);
52 lvb_lvds_phy_lane_init(lvb_base, lvb_lvds_lane_idx_lvds0_txck, &lvds_lane_cfg);
53 lvb_lvds_phy_lane_init(lvb_base, lvb_lvds_lane_idx_lvds1_tx0, &lvds_lane_cfg);
54 lvb_lvds_phy_lane_init(lvb_base, lvb_lvds_lane_idx_lvds1_tx1, &lvds_lane_cfg);
55 lvb_lvds_phy_lane_init(lvb_base, lvb_lvds_lane_idx_lvds1_tx2, &lvds_lane_cfg);
56 lvb_lvds_phy_lane_init(lvb_base, lvb_lvds_lane_idx_lvds1_tx3, &lvds_lane_cfg);
57 lvb_lvds_phy_lane_init(lvb_base, lvb_lvds_lane_idx_lvds1_txck, &lvds_lane_cfg);
58
59 lvb_lvds_phy0_poweron(lvb_base);
60 lvb_lvds_phy1_poweron(lvb_base);
61
62 while (lvb_lvds_phy_split_pll_is_lock(lvb_base) == false) {
63 }
64 }
65
reset(hpm_panel_t * panel)66 static void reset(hpm_panel_t *panel)
67 {
68 if (!panel->hw_if.set_reset_pin_level)
69 return;
70
71 panel->hw_if.set_reset_pin_level(0);
72 hpm_panel_delay_us(2000);
73
74 panel->hw_if.set_reset_pin_level(1);
75 hpm_panel_delay_us(2000);
76 }
77
init(hpm_panel_t * panel)78 static void init(hpm_panel_t *panel)
79 {
80 if (panel->hw_if.set_video_router)
81 panel->hw_if.set_video_router();
82
83 lvds_panel_lvb_init(panel);
84 lvds_panel_phy_init(panel);
85 }
86
87 hpm_panel_t panel_tm103xdgp01 = {
88 .name = "tm103xdgp01",
89 .if_type = HPM_PANEL_IF_TYPE_LVDS_SPLIT,
90 .timing = {
91 .pixel_clock_khz = 45000,
92 .hactive = 1920,
93 .hfront_porch = 32,
94 .hback_porch = 32,
95 .hsync_len = 64,
96
97 .vactive = 720,
98 .vfront_porch = 2,
99 .vback_porch = 2,
100 .vsync_len = 4,
101 },
102 .funcs = {
103 .reset = reset,
104 .init = init,
105 },
106 };
107
108