Lines Matching +full:mux +full:- +full:clock

1 // SPDX-License-Identifier: GPL-2.0+
3 * i.MX drm driver - LVDS display bridge
11 #include <linux/media-bus-format.h>
13 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
33 #include "imx-drm.h"
35 #define DRIVER_NAME "imx-ldb"
73 return container_of(e, struct imx_ldb_encoder, encoder)->channel; in enc_to_imx_ldb_ch()
86 struct clk *clk[2]; /* our own clock */
87 struct clk *clk_sel[4]; /* parent of display clock */
89 struct clk *clk_pll[2]; /* upstream clock we can adjust */
97 struct imx_ldb *ldb = imx_ldb_ch->ldb; in imx_ldb_ch_set_bus_format()
98 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; in imx_ldb_ch_set_bus_format()
104 if (imx_ldb_ch->chno == 0 || dual) in imx_ldb_ch_set_bus_format()
105 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24; in imx_ldb_ch_set_bus_format()
106 if (imx_ldb_ch->chno == 1 || dual) in imx_ldb_ch_set_bus_format()
107 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24; in imx_ldb_ch_set_bus_format()
110 if (imx_ldb_ch->chno == 0 || dual) in imx_ldb_ch_set_bus_format()
111 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | in imx_ldb_ch_set_bus_format()
113 if (imx_ldb_ch->chno == 1 || dual) in imx_ldb_ch_set_bus_format()
114 ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | in imx_ldb_ch_set_bus_format()
120 static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno, in imx_ldb_set_clock() argument
125 dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__, in imx_ldb_set_clock()
126 clk_get_rate(ldb->clk_pll[chno]), serial_clk); in imx_ldb_set_clock()
127 clk_set_rate(ldb->clk_pll[chno], serial_clk); in imx_ldb_set_clock()
129 dev_dbg(ldb->dev, "%s after: %ld\n", __func__, in imx_ldb_set_clock()
130 clk_get_rate(ldb->clk_pll[chno])); in imx_ldb_set_clock()
132 dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__, in imx_ldb_set_clock()
133 clk_get_rate(ldb->clk[chno]), in imx_ldb_set_clock()
135 clk_set_rate(ldb->clk[chno], di_clk); in imx_ldb_set_clock()
137 dev_dbg(ldb->dev, "%s after: %ld\n", __func__, in imx_ldb_set_clock()
138 clk_get_rate(ldb->clk[chno])); in imx_ldb_set_clock()
140 /* set display clock mux to LDB input clock */ in imx_ldb_set_clock()
141 ret = clk_set_parent(ldb->clk_sel[mux], ldb->clk[chno]); in imx_ldb_set_clock()
143 dev_err(ldb->dev, in imx_ldb_set_clock()
144 "unable to set di%d parent clock to ldb_di%d\n", mux, in imx_ldb_set_clock()
151 struct imx_ldb *ldb = imx_ldb_ch->ldb; in imx_ldb_encoder_enable()
152 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; in imx_ldb_encoder_enable()
153 int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder); in imx_ldb_encoder_enable() local
155 if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) { in imx_ldb_encoder_enable()
156 dev_warn(ldb->dev, "%s: invalid mux %d\n", __func__, mux); in imx_ldb_encoder_enable()
161 clk_set_parent(ldb->clk_sel[mux], ldb->clk[0]); in imx_ldb_encoder_enable()
162 clk_set_parent(ldb->clk_sel[mux], ldb->clk[1]); in imx_ldb_encoder_enable()
164 clk_prepare_enable(ldb->clk[0]); in imx_ldb_encoder_enable()
165 clk_prepare_enable(ldb->clk[1]); in imx_ldb_encoder_enable()
167 clk_set_parent(ldb->clk_sel[mux], ldb->clk[imx_ldb_ch->chno]); in imx_ldb_encoder_enable()
170 if (imx_ldb_ch == &ldb->channel[0] || dual) { in imx_ldb_encoder_enable()
171 ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; in imx_ldb_encoder_enable()
172 if (mux == 0 || ldb->lvds_mux) in imx_ldb_encoder_enable()
173 ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI0; in imx_ldb_encoder_enable()
174 else if (mux == 1) in imx_ldb_encoder_enable()
175 ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI1; in imx_ldb_encoder_enable()
177 if (imx_ldb_ch == &ldb->channel[1] || dual) { in imx_ldb_encoder_enable()
178 ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK; in imx_ldb_encoder_enable()
179 if (mux == 1 || ldb->lvds_mux) in imx_ldb_encoder_enable()
180 ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI1; in imx_ldb_encoder_enable()
181 else if (mux == 0) in imx_ldb_encoder_enable()
182 ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI0; in imx_ldb_encoder_enable()
185 if (ldb->lvds_mux) { in imx_ldb_encoder_enable()
188 if (imx_ldb_ch == &ldb->channel[0]) in imx_ldb_encoder_enable()
189 lvds_mux = &ldb->lvds_mux[0]; in imx_ldb_encoder_enable()
190 else if (imx_ldb_ch == &ldb->channel[1]) in imx_ldb_encoder_enable()
191 lvds_mux = &ldb->lvds_mux[1]; in imx_ldb_encoder_enable()
193 regmap_update_bits(ldb->regmap, lvds_mux->reg, lvds_mux->mask, in imx_ldb_encoder_enable()
194 mux << lvds_mux->shift); in imx_ldb_encoder_enable()
197 regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl); in imx_ldb_encoder_enable()
206 struct drm_display_mode *mode = &crtc_state->adjusted_mode; in imx_ldb_encoder_atomic_mode_set()
207 struct imx_ldb *ldb = imx_ldb_ch->ldb; in imx_ldb_encoder_atomic_mode_set()
208 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; in imx_ldb_encoder_atomic_mode_set()
210 unsigned long di_clk = mode->clock * 1000; in imx_ldb_encoder_atomic_mode_set()
211 int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder); in imx_ldb_encoder_atomic_mode_set() local
212 u32 bus_format = imx_ldb_ch->bus_format; in imx_ldb_encoder_atomic_mode_set()
214 if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) { in imx_ldb_encoder_atomic_mode_set()
215 dev_warn(ldb->dev, "%s: invalid mux %d\n", __func__, mux); in imx_ldb_encoder_atomic_mode_set()
219 if (mode->clock > 170000) { in imx_ldb_encoder_atomic_mode_set()
220 dev_warn(ldb->dev, in imx_ldb_encoder_atomic_mode_set()
221 "%s: mode exceeds 170 MHz pixel clock\n", __func__); in imx_ldb_encoder_atomic_mode_set()
223 if (mode->clock > 85000 && !dual) { in imx_ldb_encoder_atomic_mode_set()
224 dev_warn(ldb->dev, in imx_ldb_encoder_atomic_mode_set()
225 "%s: mode exceeds 85 MHz pixel clock\n", __func__); in imx_ldb_encoder_atomic_mode_set()
228 if (!IS_ALIGNED(mode->hdisplay, 8)) { in imx_ldb_encoder_atomic_mode_set()
229 dev_warn(ldb->dev, in imx_ldb_encoder_atomic_mode_set()
234 serial_clk = 3500UL * mode->clock; in imx_ldb_encoder_atomic_mode_set()
235 imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk); in imx_ldb_encoder_atomic_mode_set()
236 imx_ldb_set_clock(ldb, mux, 1, serial_clk, di_clk); in imx_ldb_encoder_atomic_mode_set()
238 serial_clk = 7000UL * mode->clock; in imx_ldb_encoder_atomic_mode_set()
239 imx_ldb_set_clock(ldb, mux, imx_ldb_ch->chno, serial_clk, in imx_ldb_encoder_atomic_mode_set()
243 /* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */ in imx_ldb_encoder_atomic_mode_set()
244 if (imx_ldb_ch == &ldb->channel[0] || dual) { in imx_ldb_encoder_atomic_mode_set()
245 if (mode->flags & DRM_MODE_FLAG_NVSYNC) in imx_ldb_encoder_atomic_mode_set()
246 ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW; in imx_ldb_encoder_atomic_mode_set()
247 else if (mode->flags & DRM_MODE_FLAG_PVSYNC) in imx_ldb_encoder_atomic_mode_set()
248 ldb->ldb_ctrl &= ~LDB_DI0_VS_POL_ACT_LOW; in imx_ldb_encoder_atomic_mode_set()
250 if (imx_ldb_ch == &ldb->channel[1] || dual) { in imx_ldb_encoder_atomic_mode_set()
251 if (mode->flags & DRM_MODE_FLAG_NVSYNC) in imx_ldb_encoder_atomic_mode_set()
252 ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW; in imx_ldb_encoder_atomic_mode_set()
253 else if (mode->flags & DRM_MODE_FLAG_PVSYNC) in imx_ldb_encoder_atomic_mode_set()
254 ldb->ldb_ctrl &= ~LDB_DI1_VS_POL_ACT_LOW; in imx_ldb_encoder_atomic_mode_set()
258 struct drm_connector *connector = connector_state->connector; in imx_ldb_encoder_atomic_mode_set()
259 struct drm_display_info *di = &connector->display_info; in imx_ldb_encoder_atomic_mode_set()
261 if (di->num_bus_formats) in imx_ldb_encoder_atomic_mode_set()
262 bus_format = di->bus_formats[0]; in imx_ldb_encoder_atomic_mode_set()
270 struct imx_ldb *ldb = imx_ldb_ch->ldb; in imx_ldb_encoder_disable()
271 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; in imx_ldb_encoder_disable()
272 int mux, ret; in imx_ldb_encoder_disable() local
274 if (imx_ldb_ch == &ldb->channel[0] || dual) in imx_ldb_encoder_disable()
275 ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; in imx_ldb_encoder_disable()
276 if (imx_ldb_ch == &ldb->channel[1] || dual) in imx_ldb_encoder_disable()
277 ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK; in imx_ldb_encoder_disable()
279 regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl); in imx_ldb_encoder_disable()
282 clk_disable_unprepare(ldb->clk[0]); in imx_ldb_encoder_disable()
283 clk_disable_unprepare(ldb->clk[1]); in imx_ldb_encoder_disable()
286 if (ldb->lvds_mux) { in imx_ldb_encoder_disable()
289 if (imx_ldb_ch == &ldb->channel[0]) in imx_ldb_encoder_disable()
290 lvds_mux = &ldb->lvds_mux[0]; in imx_ldb_encoder_disable()
291 else if (imx_ldb_ch == &ldb->channel[1]) in imx_ldb_encoder_disable()
292 lvds_mux = &ldb->lvds_mux[1]; in imx_ldb_encoder_disable()
294 regmap_read(ldb->regmap, lvds_mux->reg, &mux); in imx_ldb_encoder_disable()
295 mux &= lvds_mux->mask; in imx_ldb_encoder_disable()
296 mux >>= lvds_mux->shift; in imx_ldb_encoder_disable()
298 mux = (imx_ldb_ch == &ldb->channel[0]) ? 0 : 1; in imx_ldb_encoder_disable()
301 /* set display clock mux back to original input clock */ in imx_ldb_encoder_disable()
302 ret = clk_set_parent(ldb->clk_sel[mux], ldb->clk_parent[mux]); in imx_ldb_encoder_disable()
304 dev_err(ldb->dev, in imx_ldb_encoder_disable()
305 "unable to set di%d parent clock to original parent\n", in imx_ldb_encoder_disable()
306 mux); in imx_ldb_encoder_disable()
315 struct drm_display_info *di = &conn_state->connector->display_info; in imx_ldb_encoder_atomic_check()
316 u32 bus_format = imx_ldb_ch->bus_format; in imx_ldb_encoder_atomic_check()
319 if (!bus_format && di->num_bus_formats) { in imx_ldb_encoder_atomic_check()
320 bus_format = di->bus_formats[0]; in imx_ldb_encoder_atomic_check()
322 bus_format = imx_ldb_ch->bus_format; in imx_ldb_encoder_atomic_check()
325 imx_crtc_state->bus_flags = di->bus_flags; in imx_ldb_encoder_atomic_check()
329 imx_crtc_state->bus_format = MEDIA_BUS_FMT_RGB666_1X18; in imx_ldb_encoder_atomic_check()
333 imx_crtc_state->bus_format = MEDIA_BUS_FMT_RGB888_1X24; in imx_ldb_encoder_atomic_check()
336 return -EINVAL; in imx_ldb_encoder_atomic_check()
339 imx_crtc_state->di_hsync_pin = 2; in imx_ldb_encoder_atomic_check()
340 imx_crtc_state->di_vsync_pin = 3; in imx_ldb_encoder_atomic_check()
358 ldb->clk[chno] = devm_clk_get(ldb->dev, clkname); in imx_ldb_get_clk()
359 if (IS_ERR(ldb->clk[chno])) in imx_ldb_get_clk()
360 return PTR_ERR(ldb->clk[chno]); in imx_ldb_get_clk()
363 ldb->clk_pll[chno] = devm_clk_get(ldb->dev, clkname); in imx_ldb_get_clk()
365 return PTR_ERR_OR_ZERO(ldb->clk_pll[chno]); in imx_ldb_get_clk()
371 struct imx_ldb *ldb = imx_ldb_ch->ldb; in imx_ldb_register()
382 ldb_encoder->channel = imx_ldb_ch; in imx_ldb_register()
383 encoder = &ldb_encoder->encoder; in imx_ldb_register()
385 ret = imx_drm_encoder_parse_of(drm, encoder, imx_ldb_ch->child); in imx_ldb_register()
389 ret = imx_ldb_get_clk(ldb, imx_ldb_ch->chno); in imx_ldb_register()
393 if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) { in imx_ldb_register()
401 ret = drm_bridge_attach(encoder, imx_ldb_ch->bridge, NULL, in imx_ldb_register()
433 ret = of_property_read_string(np, "fsl,data-mapping", &bm); in of_get_bus_format()
437 of_property_read_u32(np, "fsl,data-width", &datawidth); in of_get_bus_format()
445 dev_err(dev, "invalid data mapping: %d-bit \"%s\"\n", datawidth, bm); in of_get_bus_format()
447 return -ENOENT; in of_get_bus_format()
463 * For a device declaring compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb",
466 * entries (in this case fsl,imx53-ldb) need to be ordered last.
469 { .compatible = "fsl,imx6q-ldb", .data = imx6q_lvds_mux, },
470 { .compatible = "fsl,imx53-ldb", .data = NULL, },
483 struct imx_ldb_channel *channel = &imx_ldb->channel[i]; in imx_ldb_bind()
485 if (!channel->ldb) in imx_ldb_bind()
502 struct device *dev = &pdev->dev; in imx_ldb_probe()
503 struct device_node *np = dev->of_node; in imx_ldb_probe()
512 return -ENOMEM; in imx_ldb_probe()
514 imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr"); in imx_ldb_probe()
515 if (IS_ERR(imx_ldb->regmap)) { in imx_ldb_probe()
517 return PTR_ERR(imx_ldb->regmap); in imx_ldb_probe()
521 regmap_write(imx_ldb->regmap, IOMUXC_GPR2, 0); in imx_ldb_probe()
523 imx_ldb->dev = dev; in imx_ldb_probe()
524 imx_ldb->lvds_mux = device_get_match_data(dev); in imx_ldb_probe()
526 dual = of_property_read_bool(np, "fsl,dual-channel"); in imx_ldb_probe()
528 imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN; in imx_ldb_probe()
531 * There are three different possible clock mux configurations: in imx_ldb_probe()
541 imx_ldb->clk_sel[i] = devm_clk_get(imx_ldb->dev, clkname); in imx_ldb_probe()
542 if (IS_ERR(imx_ldb->clk_sel[i])) { in imx_ldb_probe()
543 ret = PTR_ERR(imx_ldb->clk_sel[i]); in imx_ldb_probe()
544 imx_ldb->clk_sel[i] = NULL; in imx_ldb_probe()
548 imx_ldb->clk_parent[i] = clk_get_parent(imx_ldb->clk_sel[i]); in imx_ldb_probe()
559 ret = -EINVAL; in imx_ldb_probe()
567 dev_warn(dev, "dual-channel mode, ignoring second output\n"); in imx_ldb_probe()
571 channel = &imx_ldb->channel[i]; in imx_ldb_probe()
572 channel->ldb = imx_ldb; in imx_ldb_probe()
573 channel->chno = i; in imx_ldb_probe()
576 * The output port is port@4 with an external 4-port mux or in imx_ldb_probe()
577 * port@2 with the internal 2-port mux. in imx_ldb_probe()
579 channel->bridge = devm_drm_of_get_bridge(dev, child, in imx_ldb_probe()
580 imx_ldb->lvds_mux ? 4 : 2, 0); in imx_ldb_probe()
581 if (IS_ERR(channel->bridge)) { in imx_ldb_probe()
582 ret = PTR_ERR(channel->bridge); in imx_ldb_probe()
583 if (ret != -ENODEV) in imx_ldb_probe()
585 channel->bridge = NULL; in imx_ldb_probe()
593 if (bus_format == -EINVAL && channel->bridge) in imx_ldb_probe()
601 channel->bus_format = bus_format; in imx_ldb_probe()
607 if (!channel->bridge) { in imx_ldb_probe()
608 channel->bridge = devm_imx_drm_legacy_bridge(dev, child, in imx_ldb_probe()
610 if (IS_ERR(channel->bridge)) { in imx_ldb_probe()
611 ret = PTR_ERR(channel->bridge); in imx_ldb_probe()
616 channel->child = child; in imx_ldb_probe()
621 return component_add(&pdev->dev, &imx_ldb_ops); in imx_ldb_probe()
630 component_del(&pdev->dev, &imx_ldb_ops); in imx_ldb_remove()