Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * rcar_lvds.c  --  R-Car LVDS Encoder
  4 *
  5 * Copyright (C) 2013-2018 Renesas Electronics Corporation
  6 *
  7 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  8 */
  9
 10#include <linux/clk.h>
 11#include <linux/delay.h>
 12#include <linux/io.h>
 13#include <linux/of.h>
 14#include <linux/of_device.h>
 15#include <linux/of_graph.h>
 16#include <linux/platform_device.h>
 17#include <linux/slab.h>
 18
 19#include <drm/drm_atomic.h>
 20#include <drm/drm_atomic_helper.h>
 21#include <drm/drm_bridge.h>
 22#include <drm/drm_crtc_helper.h>
 23#include <drm/drm_panel.h>
 24
 25#include "rcar_lvds_regs.h"
 26
 27/* Keep in sync with the LVDCR0.LVMD hardware register values. */
 28enum rcar_lvds_mode {
 29	RCAR_LVDS_MODE_JEIDA = 0,
 30	RCAR_LVDS_MODE_MIRROR = 1,
 31	RCAR_LVDS_MODE_VESA = 4,
 32};
 33
 34#define RCAR_LVDS_QUIRK_LANES	(1 << 0)	/* LVDS lanes 1 and 3 inverted */
 35#define RCAR_LVDS_QUIRK_GEN2_PLLCR (1 << 1)	/* LVDPLLCR has gen2 layout */
 36#define RCAR_LVDS_QUIRK_GEN3_LVEN (1 << 2)	/* LVEN bit needs to be set */
 37						/* on R8A77970/R8A7799x */
 38
 39struct rcar_lvds_device_info {
 40	unsigned int gen;
 41	unsigned int quirks;
 42};
 43
 44struct rcar_lvds {
 45	struct device *dev;
 46	const struct rcar_lvds_device_info *info;
 47
 48	struct drm_bridge bridge;
 49
 50	struct drm_bridge *next_bridge;
 51	struct drm_connector connector;
 52	struct drm_panel *panel;
 53
 54	void __iomem *mmio;
 55	struct clk *clock;
 56	bool enabled;
 57
 58	struct drm_display_mode display_mode;
 59	enum rcar_lvds_mode mode;
 60};
 61
 62#define bridge_to_rcar_lvds(bridge) \
 63	container_of(bridge, struct rcar_lvds, bridge)
 64
 65#define connector_to_rcar_lvds(connector) \
 66	container_of(connector, struct rcar_lvds, connector)
 67
 68static void rcar_lvds_write(struct rcar_lvds *lvds, u32 reg, u32 data)
 69{
 70	iowrite32(data, lvds->mmio + reg);
 71}
 72
 73/* -----------------------------------------------------------------------------
 74 * Connector & Panel
 75 */
 76
 77static int rcar_lvds_connector_get_modes(struct drm_connector *connector)
 78{
 79	struct rcar_lvds *lvds = connector_to_rcar_lvds(connector);
 80
 81	return drm_panel_get_modes(lvds->panel);
 82}
 83
 84static int rcar_lvds_connector_atomic_check(struct drm_connector *connector,
 85					    struct drm_connector_state *state)
 86{
 87	struct rcar_lvds *lvds = connector_to_rcar_lvds(connector);
 88	const struct drm_display_mode *panel_mode;
 89	struct drm_crtc_state *crtc_state;
 90
 91	if (!state->crtc)
 92		return 0;
 93
 94	if (list_empty(&connector->modes)) {
 95		dev_dbg(lvds->dev, "connector: empty modes list\n");
 96		return -EINVAL;
 97	}
 98
 99	panel_mode = list_first_entry(&connector->modes,
100				      struct drm_display_mode, head);
101
102	/* We're not allowed to modify the resolution. */
103	crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc);
104	if (IS_ERR(crtc_state))
105		return PTR_ERR(crtc_state);
106
107	if (crtc_state->mode.hdisplay != panel_mode->hdisplay ||
108	    crtc_state->mode.vdisplay != panel_mode->vdisplay)
109		return -EINVAL;
110
111	/* The flat panel mode is fixed, just copy it to the adjusted mode. */
112	drm_mode_copy(&crtc_state->adjusted_mode, panel_mode);
113
114	return 0;
115}
116
117static const struct drm_connector_helper_funcs rcar_lvds_conn_helper_funcs = {
118	.get_modes = rcar_lvds_connector_get_modes,
119	.atomic_check = rcar_lvds_connector_atomic_check,
120};
121
122static const struct drm_connector_funcs rcar_lvds_conn_funcs = {
123	.reset = drm_atomic_helper_connector_reset,
124	.fill_modes = drm_helper_probe_single_connector_modes,
125	.destroy = drm_connector_cleanup,
126	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
127	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
128};
129
130/* -----------------------------------------------------------------------------
131 * Bridge
132 */
133
134static u32 rcar_lvds_lvdpllcr_gen2(unsigned int freq)
135{
136	if (freq < 39000)
137		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_38M;
138	else if (freq < 61000)
139		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_60M;
140	else if (freq < 121000)
141		return LVDPLLCR_CEEN | LVDPLLCR_COSEL | LVDPLLCR_PLLDLYCNT_121M;
142	else
143		return LVDPLLCR_PLLDLYCNT_150M;
144}
145
146static u32 rcar_lvds_lvdpllcr_gen3(unsigned int freq)
147{
148	if (freq < 42000)
149		return LVDPLLCR_PLLDIVCNT_42M;
150	else if (freq < 85000)
151		return LVDPLLCR_PLLDIVCNT_85M;
152	else if (freq < 128000)
153		return LVDPLLCR_PLLDIVCNT_128M;
154	else
155		return LVDPLLCR_PLLDIVCNT_148M;
156}
157
158static void rcar_lvds_enable(struct drm_bridge *bridge)
159{
160	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
161	const struct drm_display_mode *mode = &lvds->display_mode;
162	/*
163	 * FIXME: We should really retrieve the CRTC through the state, but how
164	 * do we get a state pointer?
165	 */
166	struct drm_crtc *crtc = lvds->bridge.encoder->crtc;
167	u32 lvdpllcr;
168	u32 lvdhcr;
169	u32 lvdcr0;
170	int ret;
171
172	WARN_ON(lvds->enabled);
173
174	ret = clk_prepare_enable(lvds->clock);
175	if (ret < 0)
176		return;
177
178	/*
179	 * Hardcode the channels and control signals routing for now.
180	 *
181	 * HSYNC -> CTRL0
182	 * VSYNC -> CTRL1
183	 * DISP  -> CTRL2
184	 * 0     -> CTRL3
185	 */
186	rcar_lvds_write(lvds, LVDCTRCR, LVDCTRCR_CTR3SEL_ZERO |
187			LVDCTRCR_CTR2SEL_DISP | LVDCTRCR_CTR1SEL_VSYNC |
188			LVDCTRCR_CTR0SEL_HSYNC);
189
190	if (lvds->info->quirks & RCAR_LVDS_QUIRK_LANES)
191		lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 3)
192		       | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 1);
193	else
194		lvdhcr = LVDCHCR_CHSEL_CH(0, 0) | LVDCHCR_CHSEL_CH(1, 1)
195		       | LVDCHCR_CHSEL_CH(2, 2) | LVDCHCR_CHSEL_CH(3, 3);
196
197	rcar_lvds_write(lvds, LVDCHCR, lvdhcr);
198
199	/* PLL clock configuration. */
200	if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN2_PLLCR)
201		lvdpllcr = rcar_lvds_lvdpllcr_gen2(mode->clock);
202	else
203		lvdpllcr = rcar_lvds_lvdpllcr_gen3(mode->clock);
204	rcar_lvds_write(lvds, LVDPLLCR, lvdpllcr);
205
206	/* Set the LVDS mode and select the input. */
207	lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT;
208	if (drm_crtc_index(crtc) == 2)
209		lvdcr0 |= LVDCR0_DUSEL;
210	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
211
212	/* Turn all the channels on. */
213	rcar_lvds_write(lvds, LVDCR1,
214			LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) |
215			LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY);
216
217	if (lvds->info->gen < 3) {
218		/* Enable LVDS operation and turn the bias circuitry on. */
219		lvdcr0 |= LVDCR0_BEN | LVDCR0_LVEN;
220		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
221	}
222
223	/* Turn the PLL on. */
224	lvdcr0 |= LVDCR0_PLLON;
225	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
226
227	if (lvds->info->gen > 2) {
228		/* Set LVDS normal mode. */
229		lvdcr0 |= LVDCR0_PWD;
230		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
231	}
232
233	if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN3_LVEN) {
234		/* Turn on the LVDS PHY. */
235		lvdcr0 |= LVDCR0_LVEN;
236		rcar_lvds_write(lvds, LVDCR0, lvdcr0);
237	}
238
239	/* Wait for the startup delay. */
240	usleep_range(100, 150);
241
242	/* Turn the output on. */
243	lvdcr0 |= LVDCR0_LVRES;
244	rcar_lvds_write(lvds, LVDCR0, lvdcr0);
245
246	if (lvds->panel) {
247		drm_panel_prepare(lvds->panel);
248		drm_panel_enable(lvds->panel);
249	}
250
251	lvds->enabled = true;
252}
253
254static void rcar_lvds_disable(struct drm_bridge *bridge)
255{
256	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
257
258	WARN_ON(!lvds->enabled);
259
260	if (lvds->panel) {
261		drm_panel_disable(lvds->panel);
262		drm_panel_unprepare(lvds->panel);
263	}
264
265	rcar_lvds_write(lvds, LVDCR0, 0);
266	rcar_lvds_write(lvds, LVDCR1, 0);
267
268	clk_disable_unprepare(lvds->clock);
269
270	lvds->enabled = false;
271}
272
273static bool rcar_lvds_mode_fixup(struct drm_bridge *bridge,
274				 const struct drm_display_mode *mode,
275				 struct drm_display_mode *adjusted_mode)
276{
277	/*
278	 * The internal LVDS encoder has a restricted clock frequency operating
279	 * range (31MHz to 148.5MHz). Clamp the clock accordingly.
280	 */
281	adjusted_mode->clock = clamp(adjusted_mode->clock, 31000, 148500);
282
283	return true;
284}
285
286static void rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds)
287{
288	struct drm_display_info *info = &lvds->connector.display_info;
289	enum rcar_lvds_mode mode;
290
291	/*
292	 * There is no API yet to retrieve LVDS mode from a bridge, only panels
293	 * are supported.
294	 */
295	if (!lvds->panel)
296		return;
297
298	if (!info->num_bus_formats || !info->bus_formats) {
299		dev_err(lvds->dev, "no LVDS bus format reported\n");
300		return;
301	}
302
303	switch (info->bus_formats[0]) {
304	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
305	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
306		mode = RCAR_LVDS_MODE_JEIDA;
307		break;
308	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
309		mode = RCAR_LVDS_MODE_VESA;
310		break;
311	default:
312		dev_err(lvds->dev, "unsupported LVDS bus format 0x%04x\n",
313			info->bus_formats[0]);
314		return;
315	}
316
317	if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
318		mode |= RCAR_LVDS_MODE_MIRROR;
319
320	lvds->mode = mode;
321}
322
323static void rcar_lvds_mode_set(struct drm_bridge *bridge,
324			       struct drm_display_mode *mode,
325			       struct drm_display_mode *adjusted_mode)
326{
327	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
328
329	WARN_ON(lvds->enabled);
330
331	lvds->display_mode = *adjusted_mode;
332
333	rcar_lvds_get_lvds_mode(lvds);
334}
335
336static int rcar_lvds_attach(struct drm_bridge *bridge)
337{
338	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
339	struct drm_connector *connector = &lvds->connector;
340	struct drm_encoder *encoder = bridge->encoder;
341	int ret;
342
343	/* If we have a next bridge just attach it. */
344	if (lvds->next_bridge)
345		return drm_bridge_attach(bridge->encoder, lvds->next_bridge,
346					 bridge);
347
348	/* Otherwise we have a panel, create a connector. */
349	ret = drm_connector_init(bridge->dev, connector, &rcar_lvds_conn_funcs,
350				 DRM_MODE_CONNECTOR_LVDS);
351	if (ret < 0)
352		return ret;
353
354	drm_connector_helper_add(connector, &rcar_lvds_conn_helper_funcs);
355
356	ret = drm_mode_connector_attach_encoder(connector, encoder);
357	if (ret < 0)
358		return ret;
359
360	return drm_panel_attach(lvds->panel, connector);
361}
362
363static void rcar_lvds_detach(struct drm_bridge *bridge)
364{
365	struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
366
367	if (lvds->panel)
368		drm_panel_detach(lvds->panel);
369}
370
371static const struct drm_bridge_funcs rcar_lvds_bridge_ops = {
372	.attach = rcar_lvds_attach,
373	.detach = rcar_lvds_detach,
374	.enable = rcar_lvds_enable,
375	.disable = rcar_lvds_disable,
376	.mode_fixup = rcar_lvds_mode_fixup,
377	.mode_set = rcar_lvds_mode_set,
378};
379
380/* -----------------------------------------------------------------------------
381 * Probe & Remove
382 */
383
384static int rcar_lvds_parse_dt(struct rcar_lvds *lvds)
385{
386	struct device_node *local_output = NULL;
387	struct device_node *remote_input = NULL;
388	struct device_node *remote = NULL;
389	struct device_node *node;
390	bool is_bridge = false;
391	int ret = 0;
392
393	local_output = of_graph_get_endpoint_by_regs(lvds->dev->of_node, 1, 0);
394	if (!local_output) {
395		dev_dbg(lvds->dev, "unconnected port@1\n");
396		return -ENODEV;
397	}
398
399	/*
400	 * Locate the connected entity and infer its type from the number of
401	 * endpoints.
402	 */
403	remote = of_graph_get_remote_port_parent(local_output);
404	if (!remote) {
405		dev_dbg(lvds->dev, "unconnected endpoint %pOF\n", local_output);
406		ret = -ENODEV;
407		goto done;
408	}
409
410	if (!of_device_is_available(remote)) {
411		dev_dbg(lvds->dev, "connected entity %pOF is disabled\n",
412			remote);
413		ret = -ENODEV;
414		goto done;
415	}
416
417	remote_input = of_graph_get_remote_endpoint(local_output);
418
419	for_each_endpoint_of_node(remote, node) {
420		if (node != remote_input) {
421			/*
422			 * We've found one endpoint other than the input, this
423			 * must be a bridge.
424			 */
425			is_bridge = true;
426			of_node_put(node);
427			break;
428		}
429	}
430
431	if (is_bridge) {
432		lvds->next_bridge = of_drm_find_bridge(remote);
433		if (!lvds->next_bridge)
434			ret = -EPROBE_DEFER;
435	} else {
436		lvds->panel = of_drm_find_panel(remote);
437		if (!lvds->panel)
438			ret = -EPROBE_DEFER;
439	}
440
441done:
442	of_node_put(local_output);
443	of_node_put(remote_input);
444	of_node_put(remote);
445
446	return ret;
447}
448
449static int rcar_lvds_probe(struct platform_device *pdev)
450{
451	struct rcar_lvds *lvds;
452	struct resource *mem;
453	int ret;
454
455	lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
456	if (lvds == NULL)
457		return -ENOMEM;
458
459	platform_set_drvdata(pdev, lvds);
460
461	lvds->dev = &pdev->dev;
462	lvds->info = of_device_get_match_data(&pdev->dev);
463	lvds->enabled = false;
464
465	ret = rcar_lvds_parse_dt(lvds);
466	if (ret < 0)
467		return ret;
468
469	lvds->bridge.driver_private = lvds;
470	lvds->bridge.funcs = &rcar_lvds_bridge_ops;
471	lvds->bridge.of_node = pdev->dev.of_node;
472
473	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
474	lvds->mmio = devm_ioremap_resource(&pdev->dev, mem);
475	if (IS_ERR(lvds->mmio))
476		return PTR_ERR(lvds->mmio);
477
478	lvds->clock = devm_clk_get(&pdev->dev, NULL);
479	if (IS_ERR(lvds->clock)) {
480		dev_err(&pdev->dev, "failed to get clock\n");
481		return PTR_ERR(lvds->clock);
482	}
483
484	drm_bridge_add(&lvds->bridge);
485
486	return 0;
487}
488
489static int rcar_lvds_remove(struct platform_device *pdev)
490{
491	struct rcar_lvds *lvds = platform_get_drvdata(pdev);
492
493	drm_bridge_remove(&lvds->bridge);
494
495	return 0;
496}
497
498static const struct rcar_lvds_device_info rcar_lvds_gen2_info = {
499	.gen = 2,
500	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR,
501};
502
503static const struct rcar_lvds_device_info rcar_lvds_r8a7790_info = {
504	.gen = 2,
505	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_LANES,
506};
507
508static const struct rcar_lvds_device_info rcar_lvds_gen3_info = {
509	.gen = 3,
510};
511
512static const struct rcar_lvds_device_info rcar_lvds_r8a77970_info = {
513	.gen = 3,
514	.quirks = RCAR_LVDS_QUIRK_GEN2_PLLCR | RCAR_LVDS_QUIRK_GEN3_LVEN,
515};
516
517static const struct of_device_id rcar_lvds_of_table[] = {
518	{ .compatible = "renesas,r8a7743-lvds", .data = &rcar_lvds_gen2_info },
519	{ .compatible = "renesas,r8a7790-lvds", .data = &rcar_lvds_r8a7790_info },
520	{ .compatible = "renesas,r8a7791-lvds", .data = &rcar_lvds_gen2_info },
521	{ .compatible = "renesas,r8a7793-lvds", .data = &rcar_lvds_gen2_info },
522	{ .compatible = "renesas,r8a7795-lvds", .data = &rcar_lvds_gen3_info },
523	{ .compatible = "renesas,r8a7796-lvds", .data = &rcar_lvds_gen3_info },
524	{ .compatible = "renesas,r8a77970-lvds", .data = &rcar_lvds_r8a77970_info },
525	{ }
526};
527
528MODULE_DEVICE_TABLE(of, rcar_lvds_of_table);
529
530static struct platform_driver rcar_lvds_platform_driver = {
531	.probe		= rcar_lvds_probe,
532	.remove		= rcar_lvds_remove,
533	.driver		= {
534		.name	= "rcar-lvds",
535		.of_match_table = rcar_lvds_of_table,
536	},
537};
538
539module_platform_driver(rcar_lvds_platform_driver);
540
541MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
542MODULE_DESCRIPTION("Renesas R-Car LVDS Encoder Driver");
543MODULE_LICENSE("GPL");