blob: 66529f70d9fdd7286dab32556d8bbf238418262a [file] [log] [blame]
Angel Ponsa2ee7612020-04-04 18:51:15 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Elyes HAOUASf765d4f2018-10-27 20:14:59 +02002
3#include <types.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +02004#include <console/console.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +02005#include <device/mmio.h>
Patrick Georgi40a3e322015-06-22 19:41:29 +02006#include <delay.h>
7#include <soc/addressmap.h>
8#include <soc/clock.h>
9#include <device/device.h>
10#include <soc/nvidia/tegra/types.h>
11#include <soc/display.h>
12#include <soc/mipi_dsi.h>
13#include <soc/tegra_dsi.h>
Elyes HAOUAS30818552019-06-23 07:03:59 +020014
Patrick Georgi40a3e322015-06-22 19:41:29 +020015#include "jdi_25x18_display/panel-jdi-lpm102a188a.h"
16
17static unsigned long dsi_pads[] = {
18 0x0c0, /* DSIA channel A & B pads */
19 0x300, /* DSIB channel A & B pads */
20};
21
22static struct tegra_mipi mipi_data = {
23 .regs = (void *)TEGRA_MIPI_CAL_BASE,
24};
25
26static inline unsigned long tegra_mipi_readl(struct tegra_mipi *mipi,
27 unsigned long reg)
28{
29 return read32(mipi->regs + (reg << 2));
30}
31
32static inline void tegra_mipi_writel(struct tegra_mipi *mipi,
33 unsigned long value, unsigned long reg)
34{
35 write32(mipi->regs + (reg << 2), value);
36}
37
38static const struct tegra_mipi_pad tegra210_mipi_pads[] = {
39 { .data = MIPI_CAL_CONFIG_CSIA, .clk = 0 },
40 { .data = MIPI_CAL_CONFIG_CSIB, .clk = 0 },
41 { .data = MIPI_CAL_CONFIG_CSIC, .clk = 0 },
42 { .data = MIPI_CAL_CONFIG_CSID, .clk = 0 },
43 { .data = MIPI_CAL_CONFIG_CSIE, .clk = 0 },
44 { .data = MIPI_CAL_CONFIG_CSIF, .clk = 0 },
45 { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK },
46 { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK },
47 { .data = MIPI_CAL_CONFIG_DSIC, .clk = MIPI_CAL_CONFIG_DSIC_CLK },
48 { .data = MIPI_CAL_CONFIG_DSID, .clk = MIPI_CAL_CONFIG_DSID_CLK },
49};
50
51static const struct tegra_mipi_soc tegra210_mipi_soc = {
52 .has_clk_lane = 1,
53 .pads = tegra210_mipi_pads,
54 .num_pads = ARRAY_SIZE(tegra210_mipi_pads),
55 .clock_enable_override = 1,
56 .needs_vclamp_ref = 0,
57 .pad_drive_down_ref = 0x0,
58 .pad_drive_up_ref = 0x3,
59 .pad_vclamp_level = 0x1,
60 .pad_vauxp_level = 0x1,
61 .hspdos = 0x0,
62 .hspuos = 0x2,
63 .termos = 0x0,
64 .hsclkpdos = 0x0,
65 .hsclkpuos = 0x2,
66};
67
68struct tegra_mipi_device *tegra_mipi_request(struct tegra_mipi_device *device,
69 int device_index)
70{
71 device->mipi = &mipi_data;
72 device->mipi->soc = &tegra210_mipi_soc;
73 device->pads = dsi_pads[device_index];
74
75 return device;
76}
77
78static int tegra_mipi_wait(struct tegra_mipi *mipi)
79{
80 u32 poll_interval_us = 1000;
81 u32 timeout_us = 250 * 1000;
82 unsigned long value;
83
84 do {
85 value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS);
86 if ((value & MIPI_CAL_STATUS_ACTIVE) == 0 &&
87 (value & MIPI_CAL_STATUS_DONE) != 0)
88 return 0;
89
90 if (timeout_us > poll_interval_us)
91 timeout_us -= poll_interval_us;
92 else
93 break;
94
95 udelay(poll_interval_us);
96 } while (1);
97
98 printk(BIOS_ERR, "%s: ERROR: timeout\n", __func__);
99 return -ETIMEDOUT;
100}
101
102int tegra_mipi_calibrate(struct tegra_mipi_device *device)
103{
104 const struct tegra_mipi_soc *soc = device->mipi->soc;
105 unsigned int i;
106 u32 value;
107 int err;
108
109 value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG0);
110 value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;
111
112 if (soc->needs_vclamp_ref)
113 value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
114
115 tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
116
117 value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
118 MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);
119 tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG1);
120
121 value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);
122 value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
123 tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
124
125 value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);
126 value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7);
127 value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7);
128 value |= MIPI_CAL_BIAS_PAD_VCLAMP(soc->pad_vclamp_level);
129 value |= MIPI_CAL_BIAS_PAD_VAUXP(soc->pad_vauxp_level);
130 tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
131
132 for (i = 0; i < soc->num_pads; i++) {
133 u32 clk = 0, data = 0;
134
135 if (device->pads & BIT(i)) {
136 data = MIPI_CAL_CONFIG_SELECT |
137 MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) |
138 MIPI_CAL_CONFIG_HSPUOS(soc->hspuos) |
139 MIPI_CAL_CONFIG_TERMOS(soc->termos);
140 clk = MIPI_CAL_CONFIG_SELECT |
141 MIPI_CAL_CONFIG_HSCLKPDOSD(soc->hsclkpdos) |
142 MIPI_CAL_CONFIG_HSCLKPUOSD(soc->hsclkpuos);
143 }
144
145 tegra_mipi_writel(device->mipi, data, soc->pads[i].data);
146
147 if (soc->has_clk_lane && soc->pads[i].clk != 0)
148 tegra_mipi_writel(device->mipi, clk, soc->pads[i].clk);
149 }
150
151 value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL);
152 value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf);
153 value &= ~MIPI_CAL_CTRL_PRESCALE(0x3);
154 value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa);
155 value |= MIPI_CAL_CTRL_PRESCALE(0x2);
156
157 if (!soc->clock_enable_override)
158 value &= ~MIPI_CAL_CTRL_CLKEN_OVR;
159 else
160 value |= MIPI_CAL_CTRL_CLKEN_OVR;
161
162 tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);
163
164 /* clear any pending status bits */
165 value = tegra_mipi_readl(device->mipi, MIPI_CAL_STATUS);
166 tegra_mipi_writel(device->mipi, value, MIPI_CAL_STATUS);
167
168 value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL);
169 value |= MIPI_CAL_CTRL_START;
170 tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);
171
172 err = tegra_mipi_wait(device->mipi);
173 if (err < 0)
174 printk(BIOS_ERR, "failed to calibrate MIPI pads: %d\n", err);
175 else
176 printk(BIOS_INFO, "MIPI calibration done\n");
177
178 value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG0);
179
180 if (soc->needs_vclamp_ref)
181 value &= ~MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
182
183 value |= MIPI_CAL_BIAS_PAD_PDVCLAMP;
184 tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
185
186 return err;
187}