aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/imx/imx-ldb.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-15 18:52:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-15 18:52:01 -0500
commit988adfdffdd43cfd841df734664727993076d7cb (patch)
tree6794f7bba8f595500c2b7d33376ad6614adcfaf2 /drivers/gpu/drm/imx/imx-ldb.c
parent26178ec11ef3c6c814bf16a0a2b9c2f7242e3c64 (diff)
parent4e0cd68115620bc3236ff4e58e4c073948629b41 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "Highlights: - AMD KFD driver merge This is the AMD HSA interface for exposing a lowlevel interface for GPGPU use. They have an open source userspace built on top of this interface, and the code looks as good as it was going to get out of tree. - Initial atomic modesetting work The need for an atomic modesetting interface to allow userspace to try and send a complete set of modesetting state to the driver has arisen, and been suffering from neglect this past year. No more, the start of the common code and changes for msm driver to use it are in this tree. Ongoing work to get the userspace ioctl finished and the code clean will probably wait until next kernel. - DisplayID 1.3 and tiled monitor exposed to userspace. Tiled monitor property is now exposed for userspace to make use of. - Rockchip drm driver merged. - imx gpu driver moved out of staging Other stuff: - core: panel - MIPI DSI + new panels. expose suggested x/y properties for virtual GPUs - i915: Initial Skylake (SKL) support gen3/4 reset work start of dri1/ums removal infoframe tracking fixes for lots of things. - nouveau: tegra k1 voltage support GM204 modesetting support GT21x memory reclocking work - radeon: CI dpm fixes GPUVM improvements Initial DPM fan control - rcar-du: HDMI support added removed some support for old boards slave encoder driver for Analog Devices adv7511 - exynos: Exynos4415 SoC support - msm: a4xx gpu support atomic helper conversion - tegra: iommu support universal plane support ganged-mode DSI support - sti: HDMI i2c improvements - vmwgfx: some late fixes. - qxl: use suggested x/y properties" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (969 commits) drm: sti: fix module compilation issue drm/i915: save/restore GMBUS freq across suspend/resume on gen4 drm: sti: correctly cleanup CRTC and planes drm: sti: add HQVDP plane drm: sti: add cursor plane drm: sti: enable auxiliary CRTC drm: sti: fix delay in VTG programming drm: sti: prepare sti_tvout to support auxiliary crtc drm: sti: use drm_crtc_vblank_{on/off} instead of drm_vblank_{on/off} drm: sti: fix hdmi avi infoframe drm: sti: remove event lock while disabling vblank drm: sti: simplify gdp code drm: sti: clear all mixer control drm: sti: remove gpio for HDMI hot plug detection drm: sti: allow to change hdmi ddc i2c adapter drm/doc: Document drm_add_modes_noedid() usage drm/i915: Remove '& 0xffff' from the mask given to WA_REG() drm/i915: Invert the mask and val arguments in wa_add() and WA_REG() drm: Zero out DRM object memory upon cleanup drm/i915/bdw: Fix the write setting up the WIZ hashing mode ...
Diffstat (limited to 'drivers/gpu/drm/imx/imx-ldb.c')
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c615
1 files changed, 615 insertions, 0 deletions
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
new file mode 100644
index 000000000000..2638dc1671d0
--- /dev/null
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -0,0 +1,615 @@
1/*
2 * i.MX drm driver - LVDS display bridge
3 *
4 * Copyright (C) 2012 Sascha Hauer, Pengutronix
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301, USA.
19 */
20
21#include <linux/module.h>
22#include <linux/clk.h>
23#include <linux/component.h>
24#include <drm/drmP.h>
25#include <drm/drm_fb_helper.h>
26#include <drm/drm_crtc_helper.h>
27#include <linux/mfd/syscon.h>
28#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
29#include <linux/of_address.h>
30#include <linux/of_device.h>
31#include <video/of_videomode.h>
32#include <linux/regmap.h>
33#include <linux/videodev2.h>
34
35#include "imx-drm.h"
36
37#define DRIVER_NAME "imx-ldb"
38
39#define LDB_CH0_MODE_EN_TO_DI0 (1 << 0)
40#define LDB_CH0_MODE_EN_TO_DI1 (3 << 0)
41#define LDB_CH0_MODE_EN_MASK (3 << 0)
42#define LDB_CH1_MODE_EN_TO_DI0 (1 << 2)
43#define LDB_CH1_MODE_EN_TO_DI1 (3 << 2)
44#define LDB_CH1_MODE_EN_MASK (3 << 2)
45#define LDB_SPLIT_MODE_EN (1 << 4)
46#define LDB_DATA_WIDTH_CH0_24 (1 << 5)
47#define LDB_BIT_MAP_CH0_JEIDA (1 << 6)
48#define LDB_DATA_WIDTH_CH1_24 (1 << 7)
49#define LDB_BIT_MAP_CH1_JEIDA (1 << 8)
50#define LDB_DI0_VS_POL_ACT_LOW (1 << 9)
51#define LDB_DI1_VS_POL_ACT_LOW (1 << 10)
52#define LDB_BGREF_RMODE_INT (1 << 15)
53
54#define con_to_imx_ldb_ch(x) container_of(x, struct imx_ldb_channel, connector)
55#define enc_to_imx_ldb_ch(x) container_of(x, struct imx_ldb_channel, encoder)
56
57struct imx_ldb;
58
59struct imx_ldb_channel {
60 struct imx_ldb *ldb;
61 struct drm_connector connector;
62 struct drm_encoder encoder;
63 struct device_node *child;
64 int chno;
65 void *edid;
66 int edid_len;
67 struct drm_display_mode mode;
68 int mode_valid;
69};
70
71struct bus_mux {
72 int reg;
73 int shift;
74 int mask;
75};
76
77struct imx_ldb {
78 struct regmap *regmap;
79 struct device *dev;
80 struct imx_ldb_channel channel[2];
81 struct clk *clk[2]; /* our own clock */
82 struct clk *clk_sel[4]; /* parent of display clock */
83 struct clk *clk_pll[2]; /* upstream clock we can adjust */
84 u32 ldb_ctrl;
85 const struct bus_mux *lvds_mux;
86};
87
88static enum drm_connector_status imx_ldb_connector_detect(
89 struct drm_connector *connector, bool force)
90{
91 return connector_status_connected;
92}
93
94static int imx_ldb_connector_get_modes(struct drm_connector *connector)
95{
96 struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
97 int num_modes = 0;
98
99 if (imx_ldb_ch->edid) {
100 drm_mode_connector_update_edid_property(connector,
101 imx_ldb_ch->edid);
102 num_modes = drm_add_edid_modes(connector, imx_ldb_ch->edid);
103 }
104
105 if (imx_ldb_ch->mode_valid) {
106 struct drm_display_mode *mode;
107
108 mode = drm_mode_create(connector->dev);
109 if (!mode)
110 return -EINVAL;
111 drm_mode_copy(mode, &imx_ldb_ch->mode);
112 mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
113 drm_mode_probed_add(connector, mode);
114 num_modes++;
115 }
116
117 return num_modes;
118}
119
120static struct drm_encoder *imx_ldb_connector_best_encoder(
121 struct drm_connector *connector)
122{
123 struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector);
124
125 return &imx_ldb_ch->encoder;
126}
127
128static void imx_ldb_encoder_dpms(struct drm_encoder *encoder, int mode)
129{
130}
131
132static bool imx_ldb_encoder_mode_fixup(struct drm_encoder *encoder,
133 const struct drm_display_mode *mode,
134 struct drm_display_mode *adjusted_mode)
135{
136 return true;
137}
138
139static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno,
140 unsigned long serial_clk, unsigned long di_clk)
141{
142 int ret;
143
144 dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__,
145 clk_get_rate(ldb->clk_pll[chno]), serial_clk);
146 clk_set_rate(ldb->clk_pll[chno], serial_clk);
147
148 dev_dbg(ldb->dev, "%s after: %ld\n", __func__,
149 clk_get_rate(ldb->clk_pll[chno]));
150
151 dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__,
152 clk_get_rate(ldb->clk[chno]),
153 (long int)di_clk);
154 clk_set_rate(ldb->clk[chno], di_clk);
155
156 dev_dbg(ldb->dev, "%s after: %ld\n", __func__,
157 clk_get_rate(ldb->clk[chno]));
158
159 /* set display clock mux to LDB input clock */
160 ret = clk_set_parent(ldb->clk_sel[mux], ldb->clk[chno]);
161 if (ret)
162 dev_err(ldb->dev,
163 "unable to set di%d parent clock to ldb_di%d\n", mux,
164 chno);
165}
166
167static void imx_ldb_encoder_prepare(struct drm_encoder *encoder)
168{
169 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
170 struct imx_ldb *ldb = imx_ldb_ch->ldb;
171 struct drm_display_mode *mode = &encoder->crtc->mode;
172 u32 pixel_fmt;
173 unsigned long serial_clk;
174 unsigned long di_clk = mode->clock * 1000;
175 int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);
176
177 if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
178 /* dual channel LVDS mode */
179 serial_clk = 3500UL * mode->clock;
180 imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk);
181 imx_ldb_set_clock(ldb, mux, 1, serial_clk, di_clk);
182 } else {
183 serial_clk = 7000UL * mode->clock;
184 imx_ldb_set_clock(ldb, mux, imx_ldb_ch->chno, serial_clk,
185 di_clk);
186 }
187
188 switch (imx_ldb_ch->chno) {
189 case 0:
190 pixel_fmt = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH0_24) ?
191 V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
192 break;
193 case 1:
194 pixel_fmt = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH1_24) ?
195 V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
196 break;
197 default:
198 dev_err(ldb->dev, "unable to config di%d panel format\n",
199 imx_ldb_ch->chno);
200 pixel_fmt = V4L2_PIX_FMT_RGB24;
201 }
202
203 imx_drm_panel_format(encoder, pixel_fmt);
204}
205
206static void imx_ldb_encoder_commit(struct drm_encoder *encoder)
207{
208 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
209 struct imx_ldb *ldb = imx_ldb_ch->ldb;
210 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
211 int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder);
212
213 if (dual) {
214 clk_prepare_enable(ldb->clk[0]);
215 clk_prepare_enable(ldb->clk[1]);
216 }
217
218 if (imx_ldb_ch == &ldb->channel[0] || dual) {
219 ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
220 if (mux == 0 || ldb->lvds_mux)
221 ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI0;
222 else if (mux == 1)
223 ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI1;
224 }
225 if (imx_ldb_ch == &ldb->channel[1] || dual) {
226 ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
227 if (mux == 1 || ldb->lvds_mux)
228 ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI1;
229 else if (mux == 0)
230 ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI0;
231 }
232
233 if (ldb->lvds_mux) {
234 const struct bus_mux *lvds_mux = NULL;
235
236 if (imx_ldb_ch == &ldb->channel[0])
237 lvds_mux = &ldb->lvds_mux[0];
238 else if (imx_ldb_ch == &ldb->channel[1])
239 lvds_mux = &ldb->lvds_mux[1];
240
241 regmap_update_bits(ldb->regmap, lvds_mux->reg, lvds_mux->mask,
242 mux << lvds_mux->shift);
243 }
244
245 regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
246}
247
248static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder,
249 struct drm_display_mode *mode,
250 struct drm_display_mode *adjusted_mode)
251{
252 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
253 struct imx_ldb *ldb = imx_ldb_ch->ldb;
254 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
255
256 if (mode->clock > 170000) {
257 dev_warn(ldb->dev,
258 "%s: mode exceeds 170 MHz pixel clock\n", __func__);
259 }
260 if (mode->clock > 85000 && !dual) {
261 dev_warn(ldb->dev,
262 "%s: mode exceeds 85 MHz pixel clock\n", __func__);
263 }
264
265 /* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */
266 if (imx_ldb_ch == &ldb->channel[0]) {
267 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
268 ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW;
269 else if (mode->flags & DRM_MODE_FLAG_PVSYNC)
270 ldb->ldb_ctrl &= ~LDB_DI0_VS_POL_ACT_LOW;
271 }
272 if (imx_ldb_ch == &ldb->channel[1]) {
273 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
274 ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW;
275 else if (mode->flags & DRM_MODE_FLAG_PVSYNC)
276 ldb->ldb_ctrl &= ~LDB_DI1_VS_POL_ACT_LOW;
277 }
278}
279
280static void imx_ldb_encoder_disable(struct drm_encoder *encoder)
281{
282 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
283 struct imx_ldb *ldb = imx_ldb_ch->ldb;
284
285 /*
286 * imx_ldb_encoder_disable is called by
287 * drm_helper_disable_unused_functions without
288 * the encoder being enabled before.
289 */
290 if (imx_ldb_ch == &ldb->channel[0] &&
291 (ldb->ldb_ctrl & LDB_CH0_MODE_EN_MASK) == 0)
292 return;
293 else if (imx_ldb_ch == &ldb->channel[1] &&
294 (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0)
295 return;
296
297 if (imx_ldb_ch == &ldb->channel[0])
298 ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
299 else if (imx_ldb_ch == &ldb->channel[1])
300 ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
301
302 regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
303
304 if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
305 clk_disable_unprepare(ldb->clk[0]);
306 clk_disable_unprepare(ldb->clk[1]);
307 }
308}
309
310static struct drm_connector_funcs imx_ldb_connector_funcs = {
311 .dpms = drm_helper_connector_dpms,
312 .fill_modes = drm_helper_probe_single_connector_modes,
313 .detect = imx_ldb_connector_detect,
314 .destroy = imx_drm_connector_destroy,
315};
316
317static struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = {
318 .get_modes = imx_ldb_connector_get_modes,
319 .best_encoder = imx_ldb_connector_best_encoder,
320};
321
322static struct drm_encoder_funcs imx_ldb_encoder_funcs = {
323 .destroy = imx_drm_encoder_destroy,
324};
325
326static struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = {
327 .dpms = imx_ldb_encoder_dpms,
328 .mode_fixup = imx_ldb_encoder_mode_fixup,
329 .prepare = imx_ldb_encoder_prepare,
330 .commit = imx_ldb_encoder_commit,
331 .mode_set = imx_ldb_encoder_mode_set,
332 .disable = imx_ldb_encoder_disable,
333};
334
335static int imx_ldb_get_clk(struct imx_ldb *ldb, int chno)
336{
337 char clkname[16];
338
339 snprintf(clkname, sizeof(clkname), "di%d", chno);
340 ldb->clk[chno] = devm_clk_get(ldb->dev, clkname);
341 if (IS_ERR(ldb->clk[chno]))
342 return PTR_ERR(ldb->clk[chno]);
343
344 snprintf(clkname, sizeof(clkname), "di%d_pll", chno);
345 ldb->clk_pll[chno] = devm_clk_get(ldb->dev, clkname);
346
347 return PTR_ERR_OR_ZERO(ldb->clk_pll[chno]);
348}
349
350static int imx_ldb_register(struct drm_device *drm,
351 struct imx_ldb_channel *imx_ldb_ch)
352{
353 struct imx_ldb *ldb = imx_ldb_ch->ldb;
354 int ret;
355
356 ret = imx_drm_encoder_parse_of(drm, &imx_ldb_ch->encoder,
357 imx_ldb_ch->child);
358 if (ret)
359 return ret;
360
361 ret = imx_ldb_get_clk(ldb, imx_ldb_ch->chno);
362 if (ret)
363 return ret;
364
365 if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
366 ret = imx_ldb_get_clk(ldb, 1);
367 if (ret)
368 return ret;
369 }
370
371 drm_encoder_helper_add(&imx_ldb_ch->encoder,
372 &imx_ldb_encoder_helper_funcs);
373 drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs,
374 DRM_MODE_ENCODER_LVDS);
375
376 drm_connector_helper_add(&imx_ldb_ch->connector,
377 &imx_ldb_connector_helper_funcs);
378 drm_connector_init(drm, &imx_ldb_ch->connector,
379 &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
380
381 drm_mode_connector_attach_encoder(&imx_ldb_ch->connector,
382 &imx_ldb_ch->encoder);
383
384 return 0;
385}
386
387enum {
388 LVDS_BIT_MAP_SPWG,
389 LVDS_BIT_MAP_JEIDA
390};
391
392static const char * const imx_ldb_bit_mappings[] = {
393 [LVDS_BIT_MAP_SPWG] = "spwg",
394 [LVDS_BIT_MAP_JEIDA] = "jeida",
395};
396
397static const int of_get_data_mapping(struct device_node *np)
398{
399 const char *bm;
400 int ret, i;
401
402 ret = of_property_read_string(np, "fsl,data-mapping", &bm);
403 if (ret < 0)
404 return ret;
405
406 for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++)
407 if (!strcasecmp(bm, imx_ldb_bit_mappings[i]))
408 return i;
409
410 return -EINVAL;
411}
412
413static struct bus_mux imx6q_lvds_mux[2] = {
414 {
415 .reg = IOMUXC_GPR3,
416 .shift = 6,
417 .mask = IMX6Q_GPR3_LVDS0_MUX_CTL_MASK,
418 }, {
419 .reg = IOMUXC_GPR3,
420 .shift = 8,
421 .mask = IMX6Q_GPR3_LVDS1_MUX_CTL_MASK,
422 }
423};
424
425/*
426 * For a device declaring compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb",
427 * of_match_device will walk through this list and take the first entry
428 * matching any of its compatible values. Therefore, the more generic
429 * entries (in this case fsl,imx53-ldb) need to be ordered last.
430 */
431static const struct of_device_id imx_ldb_dt_ids[] = {
432 { .compatible = "fsl,imx6q-ldb", .data = imx6q_lvds_mux, },
433 { .compatible = "fsl,imx53-ldb", .data = NULL, },
434 { }
435};
436MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids);
437
438static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
439{
440 struct drm_device *drm = data;
441 struct device_node *np = dev->of_node;
442 const struct of_device_id *of_id =
443 of_match_device(imx_ldb_dt_ids, dev);
444 struct device_node *child;
445 const u8 *edidp;
446 struct imx_ldb *imx_ldb;
447 int datawidth;
448 int mapping;
449 int dual;
450 int ret;
451 int i;
452
453 imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL);
454 if (!imx_ldb)
455 return -ENOMEM;
456
457 imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
458 if (IS_ERR(imx_ldb->regmap)) {
459 dev_err(dev, "failed to get parent regmap\n");
460 return PTR_ERR(imx_ldb->regmap);
461 }
462
463 imx_ldb->dev = dev;
464
465 if (of_id)
466 imx_ldb->lvds_mux = of_id->data;
467
468 dual = of_property_read_bool(np, "fsl,dual-channel");
469 if (dual)
470 imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN;
471
472 /*
473 * There are three different possible clock mux configurations:
474 * i.MX53: ipu1_di0_sel, ipu1_di1_sel
475 * i.MX6q: ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel, ipu2_di1_sel
476 * i.MX6dl: ipu1_di0_sel, ipu1_di1_sel, lcdif_sel
477 * Map them all to di0_sel...di3_sel.
478 */
479 for (i = 0; i < 4; i++) {
480 char clkname[16];
481
482 sprintf(clkname, "di%d_sel", i);
483 imx_ldb->clk_sel[i] = devm_clk_get(imx_ldb->dev, clkname);
484 if (IS_ERR(imx_ldb->clk_sel[i])) {
485 ret = PTR_ERR(imx_ldb->clk_sel[i]);
486 imx_ldb->clk_sel[i] = NULL;
487 break;
488 }
489 }
490 if (i == 0)
491 return ret;
492
493 for_each_child_of_node(np, child) {
494 struct imx_ldb_channel *channel;
495
496 ret = of_property_read_u32(child, "reg", &i);
497 if (ret || i < 0 || i > 1)
498 return -EINVAL;
499
500 if (dual && i > 0) {
501 dev_warn(dev, "dual-channel mode, ignoring second output\n");
502 continue;
503 }
504
505 if (!of_device_is_available(child))
506 continue;
507
508 channel = &imx_ldb->channel[i];
509 channel->ldb = imx_ldb;
510 channel->chno = i;
511 channel->child = child;
512
513 edidp = of_get_property(child, "edid", &channel->edid_len);
514 if (edidp) {
515 channel->edid = kmemdup(edidp, channel->edid_len,
516 GFP_KERNEL);
517 } else {
518 ret = of_get_drm_display_mode(child, &channel->mode, 0);
519 if (!ret)
520 channel->mode_valid = 1;
521 }
522
523 ret = of_property_read_u32(child, "fsl,data-width", &datawidth);
524 if (ret)
525 datawidth = 0;
526 else if (datawidth != 18 && datawidth != 24)
527 return -EINVAL;
528
529 mapping = of_get_data_mapping(child);
530 switch (mapping) {
531 case LVDS_BIT_MAP_SPWG:
532 if (datawidth == 24) {
533 if (i == 0 || dual)
534 imx_ldb->ldb_ctrl |=
535 LDB_DATA_WIDTH_CH0_24;
536 if (i == 1 || dual)
537 imx_ldb->ldb_ctrl |=
538 LDB_DATA_WIDTH_CH1_24;
539 }
540 break;
541 case LVDS_BIT_MAP_JEIDA:
542 if (datawidth == 18) {
543 dev_err(dev, "JEIDA standard only supported in 24 bit\n");
544 return -EINVAL;
545 }
546 if (i == 0 || dual)
547 imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 |
548 LDB_BIT_MAP_CH0_JEIDA;
549 if (i == 1 || dual)
550 imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 |
551 LDB_BIT_MAP_CH1_JEIDA;
552 break;
553 default:
554 dev_err(dev, "data mapping not specified or invalid\n");
555 return -EINVAL;
556 }
557
558 ret = imx_ldb_register(drm, channel);
559 if (ret)
560 return ret;
561 }
562
563 dev_set_drvdata(dev, imx_ldb);
564
565 return 0;
566}
567
568static void imx_ldb_unbind(struct device *dev, struct device *master,
569 void *data)
570{
571 struct imx_ldb *imx_ldb = dev_get_drvdata(dev);
572 int i;
573
574 for (i = 0; i < 2; i++) {
575 struct imx_ldb_channel *channel = &imx_ldb->channel[i];
576
577 if (!channel->connector.funcs)
578 continue;
579
580 channel->connector.funcs->destroy(&channel->connector);
581 channel->encoder.funcs->destroy(&channel->encoder);
582 }
583}
584
585static const struct component_ops imx_ldb_ops = {
586 .bind = imx_ldb_bind,
587 .unbind = imx_ldb_unbind,
588};
589
590static int imx_ldb_probe(struct platform_device *pdev)
591{
592 return component_add(&pdev->dev, &imx_ldb_ops);
593}
594
595static int imx_ldb_remove(struct platform_device *pdev)
596{
597 component_del(&pdev->dev, &imx_ldb_ops);
598 return 0;
599}
600
601static struct platform_driver imx_ldb_driver = {
602 .probe = imx_ldb_probe,
603 .remove = imx_ldb_remove,
604 .driver = {
605 .of_match_table = imx_ldb_dt_ids,
606 .name = DRIVER_NAME,
607 },
608};
609
610module_platform_driver(imx_ldb_driver);
611
612MODULE_DESCRIPTION("i.MX LVDS driver");
613MODULE_AUTHOR("Sascha Hauer, Pengutronix");
614MODULE_LICENSE("GPL");
615MODULE_ALIAS("platform:" DRIVER_NAME);