Commit | Line | Data |
---|---|---|
a095f15c SP |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* | |
3 | * Copyright (c) 2018, The Linux Foundation. All rights reserved. | |
4 | */ | |
5 | ||
6 | #include <drm/drmP.h> | |
7 | #include <drm/drm_atomic.h> | |
8 | #include <drm/drm_atomic_helper.h> | |
b814ec6d | 9 | #include <drm/drm_dp_helper.h> |
a095f15c SP |
10 | #include <drm/drm_mipi_dsi.h> |
11 | #include <drm/drm_of.h> | |
12 | #include <drm/drm_panel.h> | |
fcd70cd3 | 13 | #include <drm/drm_probe_helper.h> |
a095f15c SP |
14 | #include <linux/clk.h> |
15 | #include <linux/gpio/consumer.h> | |
16 | #include <linux/i2c.h> | |
b814ec6d | 17 | #include <linux/iopoll.h> |
a095f15c SP |
18 | #include <linux/of_graph.h> |
19 | #include <linux/pm_runtime.h> | |
20 | #include <linux/regmap.h> | |
21 | #include <linux/regulator/consumer.h> | |
22 | ||
a095f15c | 23 | #define SN_DEVICE_REV_REG 0x08 |
a095f15c | 24 | #define SN_DPPLL_SRC_REG 0x0A |
6c76c0eb SP |
25 | #define DPPLL_CLK_SRC_DSICLK BIT(0) |
26 | #define REFCLK_FREQ_MASK GENMASK(3, 1) | |
27 | #define REFCLK_FREQ(x) ((x) << 1) | |
28 | #define DPPLL_SRC_DP_PLL_LOCK BIT(7) | |
29 | #define SN_PLL_ENABLE_REG 0x0D | |
a095f15c | 30 | #define SN_DSI_LANES_REG 0x10 |
6c76c0eb SP |
31 | #define CHA_DSI_LANES_MASK GENMASK(4, 3) |
32 | #define CHA_DSI_LANES(x) ((x) << 3) | |
a095f15c | 33 | #define SN_DSIA_CLK_FREQ_REG 0x12 |
a095f15c SP |
34 | #define SN_CHA_ACTIVE_LINE_LENGTH_LOW_REG 0x20 |
35 | #define SN_CHA_VERTICAL_DISPLAY_SIZE_LOW_REG 0x24 | |
36 | #define SN_CHA_HSYNC_PULSE_WIDTH_LOW_REG 0x2C | |
37 | #define SN_CHA_HSYNC_PULSE_WIDTH_HIGH_REG 0x2D | |
6c76c0eb | 38 | #define CHA_HSYNC_POLARITY BIT(7) |
a095f15c SP |
39 | #define SN_CHA_VSYNC_PULSE_WIDTH_LOW_REG 0x30 |
40 | #define SN_CHA_VSYNC_PULSE_WIDTH_HIGH_REG 0x31 | |
6c76c0eb | 41 | #define CHA_VSYNC_POLARITY BIT(7) |
a095f15c SP |
42 | #define SN_CHA_HORIZONTAL_BACK_PORCH_REG 0x34 |
43 | #define SN_CHA_VERTICAL_BACK_PORCH_REG 0x36 | |
44 | #define SN_CHA_HORIZONTAL_FRONT_PORCH_REG 0x38 | |
45 | #define SN_CHA_VERTICAL_FRONT_PORCH_REG 0x3A | |
6c76c0eb SP |
46 | #define SN_ENH_FRAME_REG 0x5A |
47 | #define VSTREAM_ENABLE BIT(3) | |
a095f15c | 48 | #define SN_DATA_FORMAT_REG 0x5B |
6c76c0eb SP |
49 | #define SN_HPD_DISABLE_REG 0x5C |
50 | #define HPD_DISABLE BIT(0) | |
b814ec6d | 51 | #define SN_AUX_WDATA_REG(x) (0x64 + (x)) |
6c76c0eb SP |
52 | #define SN_AUX_ADDR_19_16_REG 0x74 |
53 | #define SN_AUX_ADDR_15_8_REG 0x75 | |
54 | #define SN_AUX_ADDR_7_0_REG 0x76 | |
55 | #define SN_AUX_LENGTH_REG 0x77 | |
56 | #define SN_AUX_CMD_REG 0x78 | |
4265b0fe | 57 | #define AUX_CMD_SEND BIT(0) |
6c76c0eb | 58 | #define AUX_CMD_REQ(x) ((x) << 4) |
b814ec6d | 59 | #define SN_AUX_RDATA_REG(x) (0x79 + (x)) |
6c76c0eb SP |
60 | #define SN_SSC_CONFIG_REG 0x93 |
61 | #define DP_NUM_LANES_MASK GENMASK(5, 4) | |
62 | #define DP_NUM_LANES(x) ((x) << 4) | |
63 | #define SN_DATARATE_CONFIG_REG 0x94 | |
64 | #define DP_DATARATE_MASK GENMASK(7, 5) | |
65 | #define DP_DATARATE(x) ((x) << 5) | |
66 | #define SN_ML_TX_MODE_REG 0x96 | |
67 | #define ML_TX_MAIN_LINK_OFF 0 | |
68 | #define ML_TX_NORMAL_MODE BIT(0) | |
b814ec6d SP |
69 | #define SN_AUX_CMD_STATUS_REG 0xF4 |
70 | #define AUX_IRQ_STATUS_AUX_RPLY_TOUT BIT(3) | |
71 | #define AUX_IRQ_STATUS_AUX_SHORT BIT(5) | |
72 | #define AUX_IRQ_STATUS_NAT_I2C_FAIL BIT(6) | |
a095f15c SP |
73 | |
74 | #define MIN_DSI_CLK_FREQ_MHZ 40 | |
75 | ||
76 | /* fudge factor required to account for 8b/10b encoding */ | |
77 | #define DP_CLK_FUDGE_NUM 10 | |
78 | #define DP_CLK_FUDGE_DEN 8 | |
79 | ||
b814ec6d SP |
80 | /* Matches DP_AUX_MAX_PAYLOAD_BYTES (for now) */ |
81 | #define SN_AUX_MAX_PAYLOAD_BYTES 16 | |
82 | ||
a095f15c SP |
83 | #define SN_REGULATOR_SUPPLY_NUM 4 |
84 | ||
85 | struct ti_sn_bridge { | |
86 | struct device *dev; | |
87 | struct regmap *regmap; | |
b814ec6d | 88 | struct drm_dp_aux aux; |
a095f15c SP |
89 | struct drm_bridge bridge; |
90 | struct drm_connector connector; | |
91 | struct device_node *host_node; | |
92 | struct mipi_dsi_device *dsi; | |
93 | struct clk *refclk; | |
94 | struct drm_panel *panel; | |
95 | struct gpio_desc *enable_gpio; | |
96 | struct regulator_bulk_data supplies[SN_REGULATOR_SUPPLY_NUM]; | |
97 | }; | |
98 | ||
99 | static const struct regmap_range ti_sn_bridge_volatile_ranges[] = { | |
100 | { .range_min = 0, .range_max = 0xFF }, | |
101 | }; | |
102 | ||
103 | static const struct regmap_access_table ti_sn_bridge_volatile_table = { | |
104 | .yes_ranges = ti_sn_bridge_volatile_ranges, | |
105 | .n_yes_ranges = ARRAY_SIZE(ti_sn_bridge_volatile_ranges), | |
106 | }; | |
107 | ||
108 | static const struct regmap_config ti_sn_bridge_regmap_config = { | |
109 | .reg_bits = 8, | |
110 | .val_bits = 8, | |
111 | .volatile_table = &ti_sn_bridge_volatile_table, | |
112 | .cache_type = REGCACHE_NONE, | |
113 | }; | |
114 | ||
115 | static void ti_sn_bridge_write_u16(struct ti_sn_bridge *pdata, | |
116 | unsigned int reg, u16 val) | |
117 | { | |
118 | regmap_write(pdata->regmap, reg, val & 0xFF); | |
119 | regmap_write(pdata->regmap, reg + 1, val >> 8); | |
120 | } | |
121 | ||
122 | static int __maybe_unused ti_sn_bridge_resume(struct device *dev) | |
123 | { | |
124 | struct ti_sn_bridge *pdata = dev_get_drvdata(dev); | |
125 | int ret; | |
126 | ||
127 | ret = regulator_bulk_enable(SN_REGULATOR_SUPPLY_NUM, pdata->supplies); | |
128 | if (ret) { | |
129 | DRM_ERROR("failed to enable supplies %d\n", ret); | |
130 | return ret; | |
131 | } | |
132 | ||
133 | gpiod_set_value(pdata->enable_gpio, 1); | |
134 | ||
135 | return ret; | |
136 | } | |
137 | ||
138 | static int __maybe_unused ti_sn_bridge_suspend(struct device *dev) | |
139 | { | |
140 | struct ti_sn_bridge *pdata = dev_get_drvdata(dev); | |
141 | int ret; | |
142 | ||
143 | gpiod_set_value(pdata->enable_gpio, 0); | |
144 | ||
145 | ret = regulator_bulk_disable(SN_REGULATOR_SUPPLY_NUM, pdata->supplies); | |
146 | if (ret) | |
147 | DRM_ERROR("failed to disable supplies %d\n", ret); | |
148 | ||
149 | return ret; | |
150 | } | |
151 | ||
152 | static const struct dev_pm_ops ti_sn_bridge_pm_ops = { | |
153 | SET_RUNTIME_PM_OPS(ti_sn_bridge_suspend, ti_sn_bridge_resume, NULL) | |
154 | }; | |
155 | ||
156 | /* Connector funcs */ | |
157 | static struct ti_sn_bridge * | |
158 | connector_to_ti_sn_bridge(struct drm_connector *connector) | |
159 | { | |
160 | return container_of(connector, struct ti_sn_bridge, connector); | |
161 | } | |
162 | ||
163 | static int ti_sn_bridge_connector_get_modes(struct drm_connector *connector) | |
164 | { | |
165 | struct ti_sn_bridge *pdata = connector_to_ti_sn_bridge(connector); | |
166 | ||
167 | return drm_panel_get_modes(pdata->panel); | |
168 | } | |
169 | ||
170 | static enum drm_mode_status | |
171 | ti_sn_bridge_connector_mode_valid(struct drm_connector *connector, | |
172 | struct drm_display_mode *mode) | |
173 | { | |
174 | /* maximum supported resolution is 4K at 60 fps */ | |
175 | if (mode->clock > 594000) | |
176 | return MODE_CLOCK_HIGH; | |
177 | ||
178 | return MODE_OK; | |
179 | } | |
180 | ||
181 | static struct drm_connector_helper_funcs ti_sn_bridge_connector_helper_funcs = { | |
182 | .get_modes = ti_sn_bridge_connector_get_modes, | |
183 | .mode_valid = ti_sn_bridge_connector_mode_valid, | |
184 | }; | |
185 | ||
186 | static enum drm_connector_status | |
187 | ti_sn_bridge_connector_detect(struct drm_connector *connector, bool force) | |
188 | { | |
189 | /** | |
190 | * TODO: Currently if drm_panel is present, then always | |
191 | * return the status as connected. Need to add support to detect | |
192 | * device state for hot pluggable scenarios. | |
193 | */ | |
194 | return connector_status_connected; | |
195 | } | |
196 | ||
197 | static const struct drm_connector_funcs ti_sn_bridge_connector_funcs = { | |
198 | .fill_modes = drm_helper_probe_single_connector_modes, | |
199 | .detect = ti_sn_bridge_connector_detect, | |
200 | .destroy = drm_connector_cleanup, | |
201 | .reset = drm_atomic_helper_connector_reset, | |
202 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, | |
203 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | |
204 | }; | |
205 | ||
206 | static struct ti_sn_bridge *bridge_to_ti_sn_bridge(struct drm_bridge *bridge) | |
207 | { | |
208 | return container_of(bridge, struct ti_sn_bridge, bridge); | |
209 | } | |
210 | ||
211 | static int ti_sn_bridge_parse_regulators(struct ti_sn_bridge *pdata) | |
212 | { | |
213 | unsigned int i; | |
214 | const char * const ti_sn_bridge_supply_names[] = { | |
215 | "vcca", "vcc", "vccio", "vpll", | |
216 | }; | |
217 | ||
218 | for (i = 0; i < SN_REGULATOR_SUPPLY_NUM; i++) | |
219 | pdata->supplies[i].supply = ti_sn_bridge_supply_names[i]; | |
220 | ||
221 | return devm_regulator_bulk_get(pdata->dev, SN_REGULATOR_SUPPLY_NUM, | |
222 | pdata->supplies); | |
223 | } | |
224 | ||
225 | static int ti_sn_bridge_attach(struct drm_bridge *bridge) | |
226 | { | |
227 | int ret, val; | |
228 | struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge); | |
229 | struct mipi_dsi_host *host; | |
230 | struct mipi_dsi_device *dsi; | |
231 | const struct mipi_dsi_device_info info = { .type = "ti_sn_bridge", | |
232 | .channel = 0, | |
233 | .node = NULL, | |
234 | }; | |
235 | ||
236 | ret = drm_connector_init(bridge->dev, &pdata->connector, | |
237 | &ti_sn_bridge_connector_funcs, | |
238 | DRM_MODE_CONNECTOR_eDP); | |
239 | if (ret) { | |
240 | DRM_ERROR("Failed to initialize connector with drm\n"); | |
241 | return ret; | |
242 | } | |
243 | ||
244 | drm_connector_helper_add(&pdata->connector, | |
245 | &ti_sn_bridge_connector_helper_funcs); | |
80e0b199 | 246 | drm_connector_attach_encoder(&pdata->connector, bridge->encoder); |
a095f15c SP |
247 | |
248 | /* | |
249 | * TODO: ideally finding host resource and dsi dev registration needs | |
250 | * to be done in bridge probe. But some existing DSI host drivers will | |
251 | * wait for any of the drm_bridge/drm_panel to get added to the global | |
252 | * bridge/panel list, before completing their probe. So if we do the | |
253 | * dsi dev registration part in bridge probe, before populating in | |
254 | * the global bridge list, then it will cause deadlock as dsi host probe | |
255 | * will never complete, neither our bridge probe. So keeping it here | |
256 | * will satisfy most of the existing host drivers. Once the host driver | |
257 | * is fixed we can move the below code to bridge probe safely. | |
258 | */ | |
259 | host = of_find_mipi_dsi_host_by_node(pdata->host_node); | |
260 | if (!host) { | |
261 | DRM_ERROR("failed to find dsi host\n"); | |
262 | ret = -ENODEV; | |
263 | goto err_dsi_host; | |
264 | } | |
265 | ||
266 | dsi = mipi_dsi_device_register_full(host, &info); | |
267 | if (IS_ERR(dsi)) { | |
268 | DRM_ERROR("failed to create dsi device\n"); | |
269 | ret = PTR_ERR(dsi); | |
270 | goto err_dsi_host; | |
271 | } | |
272 | ||
273 | /* TODO: setting to 4 lanes always for now */ | |
274 | dsi->lanes = 4; | |
275 | dsi->format = MIPI_DSI_FMT_RGB888; | |
276 | dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | | |
277 | MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE; | |
278 | ||
279 | /* check if continuous dsi clock is required or not */ | |
280 | pm_runtime_get_sync(pdata->dev); | |
281 | regmap_read(pdata->regmap, SN_DPPLL_SRC_REG, &val); | |
282 | pm_runtime_put(pdata->dev); | |
283 | if (!(val & DPPLL_CLK_SRC_DSICLK)) | |
284 | dsi->mode_flags |= MIPI_DSI_CLOCK_NON_CONTINUOUS; | |
285 | ||
286 | ret = mipi_dsi_attach(dsi); | |
287 | if (ret < 0) { | |
288 | DRM_ERROR("failed to attach dsi to host\n"); | |
289 | goto err_dsi_attach; | |
290 | } | |
291 | pdata->dsi = dsi; | |
292 | ||
293 | /* attach panel to bridge */ | |
294 | drm_panel_attach(pdata->panel, &pdata->connector); | |
295 | ||
296 | return 0; | |
297 | ||
298 | err_dsi_attach: | |
299 | mipi_dsi_device_unregister(dsi); | |
300 | err_dsi_host: | |
301 | drm_connector_cleanup(&pdata->connector); | |
302 | return ret; | |
303 | } | |
304 | ||
305 | static void ti_sn_bridge_disable(struct drm_bridge *bridge) | |
306 | { | |
307 | struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge); | |
308 | ||
309 | drm_panel_disable(pdata->panel); | |
310 | ||
311 | /* disable video stream */ | |
6c76c0eb | 312 | regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG, VSTREAM_ENABLE, 0); |
a095f15c SP |
313 | /* semi auto link training mode OFF */ |
314 | regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0); | |
315 | /* disable DP PLL */ | |
316 | regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 0); | |
317 | ||
318 | drm_panel_unprepare(pdata->panel); | |
319 | } | |
320 | ||
321 | static u32 ti_sn_bridge_get_dsi_freq(struct ti_sn_bridge *pdata) | |
322 | { | |
323 | u32 bit_rate_khz, clk_freq_khz; | |
324 | struct drm_display_mode *mode = | |
325 | &pdata->bridge.encoder->crtc->state->adjusted_mode; | |
326 | ||
327 | bit_rate_khz = mode->clock * | |
328 | mipi_dsi_pixel_format_to_bpp(pdata->dsi->format); | |
329 | clk_freq_khz = bit_rate_khz / (pdata->dsi->lanes * 2); | |
330 | ||
331 | return clk_freq_khz; | |
332 | } | |
333 | ||
334 | /* clk frequencies supported by bridge in Hz in case derived from REFCLK pin */ | |
335 | static const u32 ti_sn_bridge_refclk_lut[] = { | |
336 | 12000000, | |
337 | 19200000, | |
338 | 26000000, | |
339 | 27000000, | |
340 | 38400000, | |
341 | }; | |
342 | ||
343 | /* clk frequencies supported by bridge in Hz in case derived from DACP/N pin */ | |
344 | static const u32 ti_sn_bridge_dsiclk_lut[] = { | |
345 | 468000000, | |
346 | 384000000, | |
347 | 416000000, | |
348 | 486000000, | |
349 | 460800000, | |
350 | }; | |
351 | ||
352 | static void ti_sn_bridge_set_refclk_freq(struct ti_sn_bridge *pdata) | |
353 | { | |
354 | int i; | |
355 | u32 refclk_rate; | |
356 | const u32 *refclk_lut; | |
357 | size_t refclk_lut_size; | |
358 | ||
359 | if (pdata->refclk) { | |
360 | refclk_rate = clk_get_rate(pdata->refclk); | |
361 | refclk_lut = ti_sn_bridge_refclk_lut; | |
362 | refclk_lut_size = ARRAY_SIZE(ti_sn_bridge_refclk_lut); | |
363 | clk_prepare_enable(pdata->refclk); | |
364 | } else { | |
365 | refclk_rate = ti_sn_bridge_get_dsi_freq(pdata) * 1000; | |
366 | refclk_lut = ti_sn_bridge_dsiclk_lut; | |
367 | refclk_lut_size = ARRAY_SIZE(ti_sn_bridge_dsiclk_lut); | |
368 | } | |
369 | ||
370 | /* for i equals to refclk_lut_size means default frequency */ | |
371 | for (i = 0; i < refclk_lut_size; i++) | |
372 | if (refclk_lut[i] == refclk_rate) | |
373 | break; | |
374 | ||
6c76c0eb SP |
375 | regmap_update_bits(pdata->regmap, SN_DPPLL_SRC_REG, REFCLK_FREQ_MASK, |
376 | REFCLK_FREQ(i)); | |
a095f15c SP |
377 | } |
378 | ||
379 | /** | |
380 | * LUT index corresponds to register value and | |
381 | * LUT values corresponds to dp data rate supported | |
382 | * by the bridge in Mbps unit. | |
383 | */ | |
384 | static const unsigned int ti_sn_bridge_dp_rate_lut[] = { | |
385 | 0, 1620, 2160, 2430, 2700, 3240, 4320, 5400 | |
386 | }; | |
387 | ||
388 | static void ti_sn_bridge_set_dsi_dp_rate(struct ti_sn_bridge *pdata) | |
389 | { | |
390 | unsigned int bit_rate_mhz, clk_freq_mhz, dp_rate_mhz; | |
391 | unsigned int val, i; | |
392 | struct drm_display_mode *mode = | |
393 | &pdata->bridge.encoder->crtc->state->adjusted_mode; | |
394 | ||
395 | /* set DSIA clk frequency */ | |
396 | bit_rate_mhz = (mode->clock / 1000) * | |
397 | mipi_dsi_pixel_format_to_bpp(pdata->dsi->format); | |
398 | clk_freq_mhz = bit_rate_mhz / (pdata->dsi->lanes * 2); | |
399 | ||
400 | /* for each increment in val, frequency increases by 5MHz */ | |
401 | val = (MIN_DSI_CLK_FREQ_MHZ / 5) + | |
402 | (((clk_freq_mhz - MIN_DSI_CLK_FREQ_MHZ) / 5) & 0xFF); | |
403 | regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val); | |
404 | ||
405 | /* set DP data rate */ | |
406 | dp_rate_mhz = ((bit_rate_mhz / pdata->dsi->lanes) * DP_CLK_FUDGE_NUM) / | |
407 | DP_CLK_FUDGE_DEN; | |
408 | for (i = 0; i < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; i++) | |
409 | if (ti_sn_bridge_dp_rate_lut[i] > dp_rate_mhz) | |
410 | break; | |
411 | ||
412 | regmap_update_bits(pdata->regmap, SN_DATARATE_CONFIG_REG, | |
6c76c0eb | 413 | DP_DATARATE_MASK, DP_DATARATE(i)); |
a095f15c SP |
414 | } |
415 | ||
416 | static void ti_sn_bridge_set_video_timings(struct ti_sn_bridge *pdata) | |
417 | { | |
418 | struct drm_display_mode *mode = | |
419 | &pdata->bridge.encoder->crtc->state->adjusted_mode; | |
420 | u8 hsync_polarity = 0, vsync_polarity = 0; | |
421 | ||
422 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) | |
6c76c0eb | 423 | hsync_polarity = CHA_HSYNC_POLARITY; |
a095f15c | 424 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) |
6c76c0eb | 425 | vsync_polarity = CHA_VSYNC_POLARITY; |
a095f15c SP |
426 | |
427 | ti_sn_bridge_write_u16(pdata, SN_CHA_ACTIVE_LINE_LENGTH_LOW_REG, | |
428 | mode->hdisplay); | |
429 | ti_sn_bridge_write_u16(pdata, SN_CHA_VERTICAL_DISPLAY_SIZE_LOW_REG, | |
430 | mode->vdisplay); | |
431 | regmap_write(pdata->regmap, SN_CHA_HSYNC_PULSE_WIDTH_LOW_REG, | |
432 | (mode->hsync_end - mode->hsync_start) & 0xFF); | |
433 | regmap_write(pdata->regmap, SN_CHA_HSYNC_PULSE_WIDTH_HIGH_REG, | |
434 | (((mode->hsync_end - mode->hsync_start) >> 8) & 0x7F) | | |
435 | hsync_polarity); | |
436 | regmap_write(pdata->regmap, SN_CHA_VSYNC_PULSE_WIDTH_LOW_REG, | |
437 | (mode->vsync_end - mode->vsync_start) & 0xFF); | |
438 | regmap_write(pdata->regmap, SN_CHA_VSYNC_PULSE_WIDTH_HIGH_REG, | |
439 | (((mode->vsync_end - mode->vsync_start) >> 8) & 0x7F) | | |
440 | vsync_polarity); | |
441 | ||
442 | regmap_write(pdata->regmap, SN_CHA_HORIZONTAL_BACK_PORCH_REG, | |
443 | (mode->htotal - mode->hsync_end) & 0xFF); | |
444 | regmap_write(pdata->regmap, SN_CHA_VERTICAL_BACK_PORCH_REG, | |
445 | (mode->vtotal - mode->vsync_end) & 0xFF); | |
446 | ||
447 | regmap_write(pdata->regmap, SN_CHA_HORIZONTAL_FRONT_PORCH_REG, | |
448 | (mode->hsync_start - mode->hdisplay) & 0xFF); | |
449 | regmap_write(pdata->regmap, SN_CHA_VERTICAL_FRONT_PORCH_REG, | |
450 | (mode->vsync_start - mode->vdisplay) & 0xFF); | |
451 | ||
452 | usleep_range(10000, 10500); /* 10ms delay recommended by spec */ | |
453 | } | |
454 | ||
455 | static void ti_sn_bridge_enable(struct drm_bridge *bridge) | |
456 | { | |
457 | struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge); | |
458 | unsigned int val; | |
fc52d0ed | 459 | int ret; |
a095f15c | 460 | |
a095f15c | 461 | /* DSI_A lane config */ |
6c76c0eb | 462 | val = CHA_DSI_LANES(4 - pdata->dsi->lanes); |
a095f15c | 463 | regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG, |
6c76c0eb | 464 | CHA_DSI_LANES_MASK, val); |
a095f15c SP |
465 | |
466 | /* DP lane config */ | |
6c76c0eb SP |
467 | val = DP_NUM_LANES(pdata->dsi->lanes - 1); |
468 | regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG, DP_NUM_LANES_MASK, | |
469 | val); | |
a095f15c SP |
470 | |
471 | /* set dsi/dp clk frequency value */ | |
472 | ti_sn_bridge_set_dsi_dp_rate(pdata); | |
473 | ||
474 | /* enable DP PLL */ | |
475 | regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 1); | |
fc52d0ed SP |
476 | |
477 | ret = regmap_read_poll_timeout(pdata->regmap, SN_DPPLL_SRC_REG, val, | |
478 | val & DPPLL_SRC_DP_PLL_LOCK, 1000, | |
479 | 50 * 1000); | |
480 | if (ret) { | |
481 | DRM_ERROR("DP_PLL_LOCK polling failed (%d)\n", ret); | |
482 | return; | |
483 | } | |
a095f15c SP |
484 | |
485 | /** | |
486 | * The SN65DSI86 only supports ASSR Display Authentication method and | |
487 | * this method is enabled by default. An eDP panel must support this | |
488 | * authentication method. We need to enable this method in the eDP panel | |
489 | * at DisplayPort address 0x0010A prior to link training. | |
490 | */ | |
b814ec6d SP |
491 | drm_dp_dpcd_writeb(&pdata->aux, DP_EDP_CONFIGURATION_SET, |
492 | DP_ALTERNATE_SCRAMBLER_RESET_ENABLE); | |
a095f15c SP |
493 | |
494 | /* Semi auto link training mode */ | |
495 | regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0x0A); | |
638e9af1 SP |
496 | ret = regmap_read_poll_timeout(pdata->regmap, SN_ML_TX_MODE_REG, val, |
497 | val == ML_TX_MAIN_LINK_OFF || | |
498 | val == ML_TX_NORMAL_MODE, 1000, | |
499 | 500 * 1000); | |
500 | if (ret) { | |
501 | DRM_ERROR("Training complete polling failed (%d)\n", ret); | |
502 | return; | |
503 | } else if (val == ML_TX_MAIN_LINK_OFF) { | |
504 | DRM_ERROR("Link training failed, link is off\n"); | |
505 | return; | |
506 | } | |
a095f15c SP |
507 | |
508 | /* config video parameters */ | |
509 | ti_sn_bridge_set_video_timings(pdata); | |
510 | ||
511 | /* enable video stream */ | |
6c76c0eb SP |
512 | regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG, VSTREAM_ENABLE, |
513 | VSTREAM_ENABLE); | |
a095f15c SP |
514 | |
515 | drm_panel_enable(pdata->panel); | |
516 | } | |
517 | ||
518 | static void ti_sn_bridge_pre_enable(struct drm_bridge *bridge) | |
519 | { | |
520 | struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge); | |
521 | ||
522 | pm_runtime_get_sync(pdata->dev); | |
523 | ||
524 | /* configure bridge ref_clk */ | |
525 | ti_sn_bridge_set_refclk_freq(pdata); | |
526 | ||
c2bfc223 DA |
527 | /* |
528 | * HPD on this bridge chip is a bit useless. This is an eDP bridge | |
529 | * so the HPD is an internal signal that's only there to signal that | |
530 | * the panel is done powering up. ...but the bridge chip debounces | |
531 | * this signal by between 100 ms and 400 ms (depending on process, | |
532 | * voltage, and temperate--I measured it at about 200 ms). One | |
533 | * particular panel asserted HPD 84 ms after it was powered on meaning | |
534 | * that we saw HPD 284 ms after power on. ...but the same panel said | |
535 | * that instead of looking at HPD you could just hardcode a delay of | |
536 | * 200 ms. We'll assume that the panel driver will have the hardcoded | |
537 | * delay in its prepare and always disable HPD. | |
538 | * | |
539 | * If HPD somehow makes sense on some future panel we'll have to | |
540 | * change this to be conditional on someone specifying that HPD should | |
541 | * be used. | |
542 | */ | |
6c76c0eb SP |
543 | regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, HPD_DISABLE, |
544 | HPD_DISABLE); | |
73c89ead SP |
545 | |
546 | drm_panel_prepare(pdata->panel); | |
a095f15c SP |
547 | } |
548 | ||
549 | static void ti_sn_bridge_post_disable(struct drm_bridge *bridge) | |
550 | { | |
551 | struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge); | |
552 | ||
553 | if (pdata->refclk) | |
554 | clk_disable_unprepare(pdata->refclk); | |
555 | ||
556 | pm_runtime_put_sync(pdata->dev); | |
557 | } | |
558 | ||
559 | static const struct drm_bridge_funcs ti_sn_bridge_funcs = { | |
560 | .attach = ti_sn_bridge_attach, | |
561 | .pre_enable = ti_sn_bridge_pre_enable, | |
562 | .enable = ti_sn_bridge_enable, | |
563 | .disable = ti_sn_bridge_disable, | |
564 | .post_disable = ti_sn_bridge_post_disable, | |
565 | }; | |
566 | ||
b814ec6d SP |
567 | static struct ti_sn_bridge *aux_to_ti_sn_bridge(struct drm_dp_aux *aux) |
568 | { | |
569 | return container_of(aux, struct ti_sn_bridge, aux); | |
570 | } | |
571 | ||
572 | static ssize_t ti_sn_aux_transfer(struct drm_dp_aux *aux, | |
573 | struct drm_dp_aux_msg *msg) | |
574 | { | |
575 | struct ti_sn_bridge *pdata = aux_to_ti_sn_bridge(aux); | |
576 | u32 request = msg->request & ~DP_AUX_I2C_MOT; | |
577 | u32 request_val = AUX_CMD_REQ(msg->request); | |
578 | u8 *buf = (u8 *)msg->buffer; | |
579 | unsigned int val; | |
580 | int ret, i; | |
581 | ||
582 | if (msg->size > SN_AUX_MAX_PAYLOAD_BYTES) | |
583 | return -EINVAL; | |
584 | ||
585 | switch (request) { | |
586 | case DP_AUX_NATIVE_WRITE: | |
587 | case DP_AUX_I2C_WRITE: | |
588 | case DP_AUX_NATIVE_READ: | |
589 | case DP_AUX_I2C_READ: | |
590 | regmap_write(pdata->regmap, SN_AUX_CMD_REG, request_val); | |
591 | break; | |
592 | default: | |
593 | return -EINVAL; | |
594 | } | |
595 | ||
596 | regmap_write(pdata->regmap, SN_AUX_ADDR_19_16_REG, | |
597 | (msg->address >> 16) & 0xF); | |
598 | regmap_write(pdata->regmap, SN_AUX_ADDR_15_8_REG, | |
599 | (msg->address >> 8) & 0xFF); | |
600 | regmap_write(pdata->regmap, SN_AUX_ADDR_7_0_REG, msg->address & 0xFF); | |
601 | ||
602 | regmap_write(pdata->regmap, SN_AUX_LENGTH_REG, msg->size); | |
603 | ||
604 | if (request == DP_AUX_NATIVE_WRITE || request == DP_AUX_I2C_WRITE) { | |
605 | for (i = 0; i < msg->size; i++) | |
606 | regmap_write(pdata->regmap, SN_AUX_WDATA_REG(i), | |
607 | buf[i]); | |
608 | } | |
609 | ||
610 | regmap_write(pdata->regmap, SN_AUX_CMD_REG, request_val | AUX_CMD_SEND); | |
611 | ||
612 | ret = regmap_read_poll_timeout(pdata->regmap, SN_AUX_CMD_REG, val, | |
613 | !(val & AUX_CMD_SEND), 200, | |
614 | 50 * 1000); | |
615 | if (ret) | |
616 | return ret; | |
617 | ||
618 | ret = regmap_read(pdata->regmap, SN_AUX_CMD_STATUS_REG, &val); | |
619 | if (ret) | |
620 | return ret; | |
621 | else if ((val & AUX_IRQ_STATUS_NAT_I2C_FAIL) | |
622 | || (val & AUX_IRQ_STATUS_AUX_RPLY_TOUT) | |
623 | || (val & AUX_IRQ_STATUS_AUX_SHORT)) | |
624 | return -ENXIO; | |
625 | ||
626 | if (request == DP_AUX_NATIVE_WRITE || request == DP_AUX_I2C_WRITE) | |
627 | return msg->size; | |
628 | ||
629 | for (i = 0; i < msg->size; i++) { | |
630 | unsigned int val; | |
631 | ret = regmap_read(pdata->regmap, SN_AUX_RDATA_REG(i), | |
632 | &val); | |
633 | if (ret) | |
634 | return ret; | |
635 | ||
636 | WARN_ON(val & ~0xFF); | |
637 | buf[i] = (u8)(val & 0xFF); | |
638 | } | |
639 | ||
640 | return msg->size; | |
641 | } | |
642 | ||
a095f15c SP |
643 | static int ti_sn_bridge_parse_dsi_host(struct ti_sn_bridge *pdata) |
644 | { | |
645 | struct device_node *np = pdata->dev->of_node; | |
646 | ||
647 | pdata->host_node = of_graph_get_remote_node(np, 0, 0); | |
648 | ||
649 | if (!pdata->host_node) { | |
650 | DRM_ERROR("remote dsi host node not found\n"); | |
651 | return -ENODEV; | |
652 | } | |
653 | ||
654 | return 0; | |
655 | } | |
656 | ||
657 | static int ti_sn_bridge_probe(struct i2c_client *client, | |
658 | const struct i2c_device_id *id) | |
659 | { | |
660 | struct ti_sn_bridge *pdata; | |
661 | int ret; | |
662 | ||
663 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | |
664 | DRM_ERROR("device doesn't support I2C\n"); | |
665 | return -ENODEV; | |
666 | } | |
667 | ||
668 | pdata = devm_kzalloc(&client->dev, sizeof(struct ti_sn_bridge), | |
669 | GFP_KERNEL); | |
670 | if (!pdata) | |
671 | return -ENOMEM; | |
672 | ||
673 | pdata->regmap = devm_regmap_init_i2c(client, | |
674 | &ti_sn_bridge_regmap_config); | |
675 | if (IS_ERR(pdata->regmap)) { | |
676 | DRM_ERROR("regmap i2c init failed\n"); | |
677 | return PTR_ERR(pdata->regmap); | |
678 | } | |
679 | ||
680 | pdata->dev = &client->dev; | |
681 | ||
682 | ret = drm_of_find_panel_or_bridge(pdata->dev->of_node, 1, 0, | |
683 | &pdata->panel, NULL); | |
684 | if (ret) { | |
685 | DRM_ERROR("could not find any panel node\n"); | |
686 | return ret; | |
687 | } | |
688 | ||
689 | dev_set_drvdata(&client->dev, pdata); | |
690 | ||
691 | pdata->enable_gpio = devm_gpiod_get(pdata->dev, "enable", | |
692 | GPIOD_OUT_LOW); | |
693 | if (IS_ERR(pdata->enable_gpio)) { | |
694 | DRM_ERROR("failed to get enable gpio from DT\n"); | |
695 | ret = PTR_ERR(pdata->enable_gpio); | |
696 | return ret; | |
697 | } | |
698 | ||
699 | ret = ti_sn_bridge_parse_regulators(pdata); | |
700 | if (ret) { | |
701 | DRM_ERROR("failed to parse regulators\n"); | |
702 | return ret; | |
703 | } | |
704 | ||
705 | pdata->refclk = devm_clk_get(pdata->dev, "refclk"); | |
706 | if (IS_ERR(pdata->refclk)) { | |
707 | ret = PTR_ERR(pdata->refclk); | |
708 | if (ret == -EPROBE_DEFER) | |
709 | return ret; | |
710 | DRM_DEBUG_KMS("refclk not found\n"); | |
711 | pdata->refclk = NULL; | |
712 | } | |
713 | ||
714 | ret = ti_sn_bridge_parse_dsi_host(pdata); | |
715 | if (ret) | |
716 | return ret; | |
717 | ||
718 | pm_runtime_enable(pdata->dev); | |
719 | ||
720 | i2c_set_clientdata(client, pdata); | |
721 | ||
b814ec6d SP |
722 | pdata->aux.name = "ti-sn65dsi86-aux"; |
723 | pdata->aux.dev = pdata->dev; | |
724 | pdata->aux.transfer = ti_sn_aux_transfer; | |
725 | drm_dp_aux_register(&pdata->aux); | |
726 | ||
a095f15c SP |
727 | pdata->bridge.funcs = &ti_sn_bridge_funcs; |
728 | pdata->bridge.of_node = client->dev.of_node; | |
729 | ||
730 | drm_bridge_add(&pdata->bridge); | |
731 | ||
732 | return 0; | |
733 | } | |
734 | ||
735 | static int ti_sn_bridge_remove(struct i2c_client *client) | |
736 | { | |
737 | struct ti_sn_bridge *pdata = i2c_get_clientdata(client); | |
738 | ||
739 | if (!pdata) | |
740 | return -EINVAL; | |
741 | ||
742 | of_node_put(pdata->host_node); | |
743 | ||
744 | pm_runtime_disable(pdata->dev); | |
745 | ||
746 | if (pdata->dsi) { | |
747 | mipi_dsi_detach(pdata->dsi); | |
748 | mipi_dsi_device_unregister(pdata->dsi); | |
749 | } | |
750 | ||
751 | drm_bridge_remove(&pdata->bridge); | |
752 | ||
753 | return 0; | |
754 | } | |
755 | ||
756 | static struct i2c_device_id ti_sn_bridge_id[] = { | |
757 | { "ti,sn65dsi86", 0}, | |
758 | {}, | |
759 | }; | |
760 | MODULE_DEVICE_TABLE(i2c, ti_sn_bridge_id); | |
761 | ||
762 | static const struct of_device_id ti_sn_bridge_match_table[] = { | |
763 | {.compatible = "ti,sn65dsi86"}, | |
764 | {}, | |
765 | }; | |
766 | MODULE_DEVICE_TABLE(of, ti_sn_bridge_match_table); | |
767 | ||
768 | static struct i2c_driver ti_sn_bridge_driver = { | |
769 | .driver = { | |
770 | .name = "ti_sn65dsi86", | |
771 | .of_match_table = ti_sn_bridge_match_table, | |
772 | .pm = &ti_sn_bridge_pm_ops, | |
773 | }, | |
774 | .probe = ti_sn_bridge_probe, | |
775 | .remove = ti_sn_bridge_remove, | |
776 | .id_table = ti_sn_bridge_id, | |
777 | }; | |
778 | module_i2c_driver(ti_sn_bridge_driver); | |
779 | ||
780 | MODULE_AUTHOR("Sandeep Panda <spanda@codeaurora.org>"); | |
781 | MODULE_DESCRIPTION("sn65dsi86 DSI to eDP bridge driver"); | |
782 | MODULE_LICENSE("GPL v2"); |