.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0+ |
---|
1 | 2 | /* |
---|
2 | 3 | * i.MX drm driver - Television Encoder (TVEv2) |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2013 Philipp Zabel, 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 | 6 | */ |
---|
15 | 7 | |
---|
16 | | -#include <linux/clk.h> |
---|
17 | 8 | #include <linux/clk-provider.h> |
---|
| 9 | +#include <linux/clk.h> |
---|
18 | 10 | #include <linux/component.h> |
---|
19 | | -#include <linux/module.h> |
---|
20 | 11 | #include <linux/i2c.h> |
---|
| 12 | +#include <linux/module.h> |
---|
| 13 | +#include <linux/platform_device.h> |
---|
21 | 14 | #include <linux/regmap.h> |
---|
22 | 15 | #include <linux/regulator/consumer.h> |
---|
23 | | -#include <linux/spinlock.h> |
---|
24 | 16 | #include <linux/videodev2.h> |
---|
25 | | -#include <drm/drmP.h> |
---|
| 17 | + |
---|
| 18 | +#include <video/imx-ipu-v3.h> |
---|
| 19 | + |
---|
26 | 20 | #include <drm/drm_atomic_helper.h> |
---|
27 | 21 | #include <drm/drm_fb_helper.h> |
---|
28 | | -#include <drm/drm_crtc_helper.h> |
---|
29 | | -#include <video/imx-ipu-v3.h> |
---|
| 22 | +#include <drm/drm_probe_helper.h> |
---|
| 23 | +#include <drm/drm_simple_kms_helper.h> |
---|
30 | 24 | |
---|
31 | 25 | #include "imx-drm.h" |
---|
32 | 26 | |
---|
.. | .. |
---|
109 | 103 | struct drm_connector connector; |
---|
110 | 104 | struct drm_encoder encoder; |
---|
111 | 105 | struct device *dev; |
---|
112 | | - spinlock_t lock; /* register lock */ |
---|
113 | | - bool enabled; |
---|
114 | 106 | int mode; |
---|
115 | 107 | int di_hsync_pin; |
---|
116 | 108 | int di_vsync_pin; |
---|
.. | .. |
---|
134 | 126 | return container_of(e, struct imx_tve, encoder); |
---|
135 | 127 | } |
---|
136 | 128 | |
---|
137 | | -static void tve_lock(void *__tve) |
---|
138 | | -__acquires(&tve->lock) |
---|
139 | | -{ |
---|
140 | | - struct imx_tve *tve = __tve; |
---|
141 | | - |
---|
142 | | - spin_lock(&tve->lock); |
---|
143 | | -} |
---|
144 | | - |
---|
145 | | -static void tve_unlock(void *__tve) |
---|
146 | | -__releases(&tve->lock) |
---|
147 | | -{ |
---|
148 | | - struct imx_tve *tve = __tve; |
---|
149 | | - |
---|
150 | | - spin_unlock(&tve->lock); |
---|
151 | | -} |
---|
152 | | - |
---|
153 | 129 | static void tve_enable(struct imx_tve *tve) |
---|
154 | 130 | { |
---|
155 | | - if (!tve->enabled) { |
---|
156 | | - tve->enabled = true; |
---|
157 | | - clk_prepare_enable(tve->clk); |
---|
158 | | - regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, |
---|
159 | | - TVE_EN, TVE_EN); |
---|
160 | | - } |
---|
| 131 | + clk_prepare_enable(tve->clk); |
---|
| 132 | + regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, TVE_EN, TVE_EN); |
---|
161 | 133 | |
---|
162 | 134 | /* clear interrupt status register */ |
---|
163 | 135 | regmap_write(tve->regmap, TVE_STAT_REG, 0xffffffff); |
---|
.. | .. |
---|
174 | 146 | |
---|
175 | 147 | static void tve_disable(struct imx_tve *tve) |
---|
176 | 148 | { |
---|
177 | | - if (tve->enabled) { |
---|
178 | | - tve->enabled = false; |
---|
179 | | - regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, TVE_EN, 0); |
---|
180 | | - clk_disable_unprepare(tve->clk); |
---|
181 | | - } |
---|
| 149 | + regmap_update_bits(tve->regmap, TVE_COM_CONF_REG, TVE_EN, 0); |
---|
| 150 | + clk_disable_unprepare(tve->clk); |
---|
182 | 151 | } |
---|
183 | 152 | |
---|
184 | 153 | static int tve_setup_tvout(struct imx_tve *tve) |
---|
.. | .. |
---|
243 | 212 | return ret; |
---|
244 | 213 | } |
---|
245 | 214 | |
---|
246 | | -static int imx_tve_connector_mode_valid(struct drm_connector *connector, |
---|
247 | | - struct drm_display_mode *mode) |
---|
| 215 | +static enum drm_mode_status |
---|
| 216 | +imx_tve_connector_mode_valid(struct drm_connector *connector, |
---|
| 217 | + struct drm_display_mode *mode) |
---|
248 | 218 | { |
---|
249 | 219 | struct imx_tve *tve = con_to_tve(connector); |
---|
250 | 220 | unsigned long rate; |
---|
.. | .. |
---|
263 | 233 | mode->hdisplay, mode->vdisplay); |
---|
264 | 234 | |
---|
265 | 235 | return MODE_BAD; |
---|
266 | | -} |
---|
267 | | - |
---|
268 | | -static struct drm_encoder *imx_tve_connector_best_encoder( |
---|
269 | | - struct drm_connector *connector) |
---|
270 | | -{ |
---|
271 | | - struct imx_tve *tve = con_to_tve(connector); |
---|
272 | | - |
---|
273 | | - return &tve->encoder; |
---|
274 | 236 | } |
---|
275 | 237 | |
---|
276 | 238 | static void imx_tve_encoder_mode_set(struct drm_encoder *encoder, |
---|
.. | .. |
---|
350 | 312 | |
---|
351 | 313 | static const struct drm_connector_helper_funcs imx_tve_connector_helper_funcs = { |
---|
352 | 314 | .get_modes = imx_tve_connector_get_modes, |
---|
353 | | - .best_encoder = imx_tve_connector_best_encoder, |
---|
354 | 315 | .mode_valid = imx_tve_connector_mode_valid, |
---|
355 | | -}; |
---|
356 | | - |
---|
357 | | -static const struct drm_encoder_funcs imx_tve_encoder_funcs = { |
---|
358 | | - .destroy = imx_drm_encoder_destroy, |
---|
359 | 316 | }; |
---|
360 | 317 | |
---|
361 | 318 | static const struct drm_encoder_helper_funcs imx_tve_encoder_helper_funcs = { |
---|
.. | .. |
---|
442 | 399 | return 0; |
---|
443 | 400 | } |
---|
444 | 401 | |
---|
445 | | -static struct clk_ops clk_tve_di_ops = { |
---|
| 402 | +static const struct clk_ops clk_tve_di_ops = { |
---|
446 | 403 | .round_rate = clk_tve_di_round_rate, |
---|
447 | 404 | .set_rate = clk_tve_di_set_rate, |
---|
448 | 405 | .recalc_rate = clk_tve_di_recalc_rate, |
---|
.. | .. |
---|
485 | 442 | return ret; |
---|
486 | 443 | |
---|
487 | 444 | drm_encoder_helper_add(&tve->encoder, &imx_tve_encoder_helper_funcs); |
---|
488 | | - drm_encoder_init(drm, &tve->encoder, &imx_tve_encoder_funcs, |
---|
489 | | - encoder_type, NULL); |
---|
| 445 | + drm_simple_encoder_init(drm, &tve->encoder, encoder_type); |
---|
490 | 446 | |
---|
491 | 447 | drm_connector_helper_add(&tve->connector, |
---|
492 | 448 | &imx_tve_connector_helper_funcs); |
---|
493 | | - drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs, |
---|
494 | | - DRM_MODE_CONNECTOR_VGA); |
---|
| 449 | + drm_connector_init_with_ddc(drm, &tve->connector, |
---|
| 450 | + &imx_tve_connector_funcs, |
---|
| 451 | + DRM_MODE_CONNECTOR_VGA, |
---|
| 452 | + tve->ddc); |
---|
495 | 453 | |
---|
496 | 454 | drm_connector_attach_encoder(&tve->connector, &tve->encoder); |
---|
497 | 455 | |
---|
.. | .. |
---|
517 | 475 | |
---|
518 | 476 | .readable_reg = imx_tve_readable_reg, |
---|
519 | 477 | |
---|
520 | | - .lock = tve_lock, |
---|
521 | | - .unlock = tve_unlock, |
---|
| 478 | + .fast_io = true, |
---|
522 | 479 | |
---|
523 | 480 | .max_register = 0xdc, |
---|
524 | 481 | }; |
---|
.. | .. |
---|
528 | 485 | [TVE_MODE_VGA] = "vga", |
---|
529 | 486 | }; |
---|
530 | 487 | |
---|
531 | | -static const int of_get_tve_mode(struct device_node *np) |
---|
| 488 | +static int of_get_tve_mode(struct device_node *np) |
---|
532 | 489 | { |
---|
533 | 490 | const char *bm; |
---|
534 | 491 | int ret, i; |
---|
.. | .. |
---|
557 | 514 | int irq; |
---|
558 | 515 | int ret; |
---|
559 | 516 | |
---|
560 | | - tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL); |
---|
561 | | - if (!tve) |
---|
562 | | - return -ENOMEM; |
---|
| 517 | + tve = dev_get_drvdata(dev); |
---|
| 518 | + memset(tve, 0, sizeof(*tve)); |
---|
563 | 519 | |
---|
564 | 520 | tve->dev = dev; |
---|
565 | | - spin_lock_init(&tve->lock); |
---|
566 | 521 | |
---|
567 | 522 | ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0); |
---|
568 | 523 | if (ddc_node) { |
---|
.. | .. |
---|
609 | 564 | } |
---|
610 | 565 | |
---|
611 | 566 | irq = platform_get_irq(pdev, 0); |
---|
612 | | - if (irq < 0) { |
---|
613 | | - dev_err(dev, "failed to get irq\n"); |
---|
| 567 | + if (irq < 0) |
---|
614 | 568 | return irq; |
---|
615 | | - } |
---|
616 | 569 | |
---|
617 | 570 | ret = devm_request_threaded_irq(dev, irq, NULL, |
---|
618 | 571 | imx_tve_irq_handler, IRQF_ONESHOT, |
---|
.. | .. |
---|
673 | 626 | if (ret) |
---|
674 | 627 | return ret; |
---|
675 | 628 | |
---|
676 | | - dev_set_drvdata(dev, tve); |
---|
677 | | - |
---|
678 | 629 | return 0; |
---|
679 | 630 | } |
---|
680 | 631 | |
---|
.. | .. |
---|
684 | 635 | |
---|
685 | 636 | static int imx_tve_probe(struct platform_device *pdev) |
---|
686 | 637 | { |
---|
| 638 | + struct imx_tve *tve; |
---|
| 639 | + |
---|
| 640 | + tve = devm_kzalloc(&pdev->dev, sizeof(*tve), GFP_KERNEL); |
---|
| 641 | + if (!tve) |
---|
| 642 | + return -ENOMEM; |
---|
| 643 | + |
---|
| 644 | + platform_set_drvdata(pdev, tve); |
---|
| 645 | + |
---|
687 | 646 | return component_add(&pdev->dev, &imx_tve_ops); |
---|
688 | 647 | } |
---|
689 | 648 | |
---|