| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (c) 2014 MediaTek Inc. |
|---|
| 3 | 4 | * Author: Jie Qiu <jie.qiu@mediatek.com> |
|---|
| 4 | | - * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 6 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 7 | | - * published by the Free Software Foundation. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 10 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 11 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 12 | | - * GNU General Public License for more details. |
|---|
| 13 | 5 | */ |
|---|
| 14 | | -#include <drm/drmP.h> |
|---|
| 15 | | -#include <drm/drm_crtc.h> |
|---|
| 16 | | -#include <drm/drm_crtc_helper.h> |
|---|
| 17 | | -#include <linux/kernel.h> |
|---|
| 18 | | -#include <linux/component.h> |
|---|
| 19 | | -#include <linux/platform_device.h> |
|---|
| 20 | | -#include <linux/of.h> |
|---|
| 21 | | -#include <linux/of_graph.h> |
|---|
| 22 | | -#include <linux/interrupt.h> |
|---|
| 23 | | -#include <linux/types.h> |
|---|
| 6 | + |
|---|
| 24 | 7 | #include <linux/clk.h> |
|---|
| 8 | +#include <linux/component.h> |
|---|
| 9 | +#include <linux/interrupt.h> |
|---|
| 10 | +#include <linux/kernel.h> |
|---|
| 11 | +#include <linux/of.h> |
|---|
| 12 | +#include <linux/of_device.h> |
|---|
| 13 | +#include <linux/of_gpio.h> |
|---|
| 14 | +#include <linux/of_graph.h> |
|---|
| 15 | +#include <linux/pinctrl/consumer.h> |
|---|
| 16 | +#include <linux/platform_device.h> |
|---|
| 17 | +#include <linux/types.h> |
|---|
| 18 | + |
|---|
| 25 | 19 | #include <video/videomode.h> |
|---|
| 20 | + |
|---|
| 21 | +#include <drm/drm_atomic_helper.h> |
|---|
| 22 | +#include <drm/drm_bridge.h> |
|---|
| 23 | +#include <drm/drm_crtc.h> |
|---|
| 24 | +#include <drm/drm_of.h> |
|---|
| 25 | +#include <drm/drm_simple_kms_helper.h> |
|---|
| 26 | 26 | |
|---|
| 27 | 27 | #include "mtk_dpi_regs.h" |
|---|
| 28 | 28 | #include "mtk_drm_ddp_comp.h" |
|---|
| .. | .. |
|---|
| 52 | 52 | }; |
|---|
| 53 | 53 | |
|---|
| 54 | 54 | enum mtk_dpi_out_color_format { |
|---|
| 55 | | - MTK_DPI_COLOR_FORMAT_RGB, |
|---|
| 56 | | - MTK_DPI_COLOR_FORMAT_RGB_FULL, |
|---|
| 57 | | - MTK_DPI_COLOR_FORMAT_YCBCR_444, |
|---|
| 58 | | - MTK_DPI_COLOR_FORMAT_YCBCR_422, |
|---|
| 59 | | - MTK_DPI_COLOR_FORMAT_XV_YCC, |
|---|
| 60 | | - MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL, |
|---|
| 61 | | - MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL |
|---|
| 55 | + MTK_DPI_COLOR_FORMAT_RGB |
|---|
| 62 | 56 | }; |
|---|
| 63 | 57 | |
|---|
| 64 | 58 | struct mtk_dpi { |
|---|
| 65 | 59 | struct mtk_ddp_comp ddp_comp; |
|---|
| 66 | 60 | struct drm_encoder encoder; |
|---|
| 67 | | - struct drm_bridge *bridge; |
|---|
| 61 | + struct drm_bridge bridge; |
|---|
| 62 | + struct drm_bridge *next_bridge; |
|---|
| 68 | 63 | void __iomem *regs; |
|---|
| 69 | 64 | struct device *dev; |
|---|
| 70 | 65 | struct clk *engine_clk; |
|---|
| .. | .. |
|---|
| 72 | 67 | struct clk *tvd_clk; |
|---|
| 73 | 68 | int irq; |
|---|
| 74 | 69 | struct drm_display_mode mode; |
|---|
| 70 | + const struct mtk_dpi_conf *conf; |
|---|
| 75 | 71 | enum mtk_dpi_out_color_format color_format; |
|---|
| 76 | 72 | enum mtk_dpi_out_yc_map yc_map; |
|---|
| 77 | 73 | enum mtk_dpi_out_bit_num bit_num; |
|---|
| 78 | 74 | enum mtk_dpi_out_channel_swap channel_swap; |
|---|
| 79 | | - bool power_sta; |
|---|
| 80 | | - u8 power_ctl; |
|---|
| 75 | + struct pinctrl *pinctrl; |
|---|
| 76 | + struct pinctrl_state *pins_gpio; |
|---|
| 77 | + struct pinctrl_state *pins_dpi; |
|---|
| 78 | + int refcount; |
|---|
| 81 | 79 | }; |
|---|
| 82 | 80 | |
|---|
| 83 | | -static inline struct mtk_dpi *mtk_dpi_from_encoder(struct drm_encoder *e) |
|---|
| 81 | +static inline struct mtk_dpi *bridge_to_dpi(struct drm_bridge *b) |
|---|
| 84 | 82 | { |
|---|
| 85 | | - return container_of(e, struct mtk_dpi, encoder); |
|---|
| 83 | + return container_of(b, struct mtk_dpi, bridge); |
|---|
| 86 | 84 | } |
|---|
| 87 | 85 | |
|---|
| 88 | 86 | enum mtk_dpi_polarity { |
|---|
| 89 | 87 | MTK_DPI_POLARITY_RISING, |
|---|
| 90 | 88 | MTK_DPI_POLARITY_FALLING, |
|---|
| 91 | | -}; |
|---|
| 92 | | - |
|---|
| 93 | | -enum mtk_dpi_power_ctl { |
|---|
| 94 | | - DPI_POWER_START = BIT(0), |
|---|
| 95 | | - DPI_POWER_ENABLE = BIT(1), |
|---|
| 96 | 89 | }; |
|---|
| 97 | 90 | |
|---|
| 98 | 91 | struct mtk_dpi_polarities { |
|---|
| .. | .. |
|---|
| 114 | 107 | u16 y_bottom; |
|---|
| 115 | 108 | u16 c_top; |
|---|
| 116 | 109 | u16 c_bottom; |
|---|
| 110 | +}; |
|---|
| 111 | + |
|---|
| 112 | +struct mtk_dpi_conf { |
|---|
| 113 | + unsigned int (*cal_factor)(int clock); |
|---|
| 114 | + u32 reg_h_fre_con; |
|---|
| 115 | + bool edge_sel_en; |
|---|
| 117 | 116 | }; |
|---|
| 118 | 117 | |
|---|
| 119 | 118 | static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) |
|---|
| .. | .. |
|---|
| 341 | 340 | |
|---|
| 342 | 341 | static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi) |
|---|
| 343 | 342 | { |
|---|
| 344 | | - mtk_dpi_mask(dpi, DPI_H_FRE_CON, H_FRE_2N, H_FRE_2N); |
|---|
| 343 | + mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N); |
|---|
| 344 | +} |
|---|
| 345 | + |
|---|
| 346 | +static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi) |
|---|
| 347 | +{ |
|---|
| 348 | + if (dpi->conf->edge_sel_en) |
|---|
| 349 | + mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN); |
|---|
| 345 | 350 | } |
|---|
| 346 | 351 | |
|---|
| 347 | 352 | static void mtk_dpi_config_color_format(struct mtk_dpi *dpi, |
|---|
| 348 | 353 | enum mtk_dpi_out_color_format format) |
|---|
| 349 | 354 | { |
|---|
| 350 | | - if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_444) || |
|---|
| 351 | | - (format == MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL)) { |
|---|
| 352 | | - mtk_dpi_config_yuv422_enable(dpi, false); |
|---|
| 353 | | - mtk_dpi_config_csc_enable(dpi, true); |
|---|
| 354 | | - mtk_dpi_config_swap_input(dpi, false); |
|---|
| 355 | | - mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_BGR); |
|---|
| 356 | | - } else if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_422) || |
|---|
| 357 | | - (format == MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL)) { |
|---|
| 358 | | - mtk_dpi_config_yuv422_enable(dpi, true); |
|---|
| 359 | | - mtk_dpi_config_csc_enable(dpi, true); |
|---|
| 360 | | - mtk_dpi_config_swap_input(dpi, true); |
|---|
| 361 | | - mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB); |
|---|
| 362 | | - } else { |
|---|
| 363 | | - mtk_dpi_config_yuv422_enable(dpi, false); |
|---|
| 364 | | - mtk_dpi_config_csc_enable(dpi, false); |
|---|
| 365 | | - mtk_dpi_config_swap_input(dpi, false); |
|---|
| 366 | | - mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB); |
|---|
| 367 | | - } |
|---|
| 355 | + /* only support RGB888 */ |
|---|
| 356 | + mtk_dpi_config_yuv422_enable(dpi, false); |
|---|
| 357 | + mtk_dpi_config_csc_enable(dpi, false); |
|---|
| 358 | + mtk_dpi_config_swap_input(dpi, false); |
|---|
| 359 | + mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB); |
|---|
| 368 | 360 | } |
|---|
| 369 | 361 | |
|---|
| 370 | | -static void mtk_dpi_power_off(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl) |
|---|
| 362 | +static void mtk_dpi_power_off(struct mtk_dpi *dpi) |
|---|
| 371 | 363 | { |
|---|
| 372 | | - dpi->power_ctl &= ~pctl; |
|---|
| 373 | | - |
|---|
| 374 | | - if ((dpi->power_ctl & DPI_POWER_START) || |
|---|
| 375 | | - (dpi->power_ctl & DPI_POWER_ENABLE)) |
|---|
| 364 | + if (WARN_ON(dpi->refcount == 0)) |
|---|
| 376 | 365 | return; |
|---|
| 377 | 366 | |
|---|
| 378 | | - if (!dpi->power_sta) |
|---|
| 367 | + if (--dpi->refcount != 0) |
|---|
| 379 | 368 | return; |
|---|
| 369 | + |
|---|
| 370 | + if (dpi->pinctrl && dpi->pins_gpio) |
|---|
| 371 | + pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio); |
|---|
| 380 | 372 | |
|---|
| 381 | 373 | mtk_dpi_disable(dpi); |
|---|
| 382 | 374 | clk_disable_unprepare(dpi->pixel_clk); |
|---|
| 383 | 375 | clk_disable_unprepare(dpi->engine_clk); |
|---|
| 384 | | - dpi->power_sta = false; |
|---|
| 385 | 376 | } |
|---|
| 386 | 377 | |
|---|
| 387 | | -static int mtk_dpi_power_on(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl) |
|---|
| 378 | +static int mtk_dpi_power_on(struct mtk_dpi *dpi) |
|---|
| 388 | 379 | { |
|---|
| 389 | 380 | int ret; |
|---|
| 390 | 381 | |
|---|
| 391 | | - dpi->power_ctl |= pctl; |
|---|
| 392 | | - |
|---|
| 393 | | - if (!(dpi->power_ctl & DPI_POWER_START) && |
|---|
| 394 | | - !(dpi->power_ctl & DPI_POWER_ENABLE)) |
|---|
| 395 | | - return 0; |
|---|
| 396 | | - |
|---|
| 397 | | - if (dpi->power_sta) |
|---|
| 382 | + if (++dpi->refcount != 1) |
|---|
| 398 | 383 | return 0; |
|---|
| 399 | 384 | |
|---|
| 400 | 385 | ret = clk_prepare_enable(dpi->engine_clk); |
|---|
| 401 | 386 | if (ret) { |
|---|
| 402 | 387 | dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret); |
|---|
| 403 | | - goto err_eng; |
|---|
| 388 | + goto err_refcount; |
|---|
| 404 | 389 | } |
|---|
| 405 | 390 | |
|---|
| 406 | 391 | ret = clk_prepare_enable(dpi->pixel_clk); |
|---|
| .. | .. |
|---|
| 409 | 394 | goto err_pixel; |
|---|
| 410 | 395 | } |
|---|
| 411 | 396 | |
|---|
| 412 | | - mtk_dpi_enable(dpi); |
|---|
| 413 | | - dpi->power_sta = true; |
|---|
| 397 | + if (dpi->pinctrl && dpi->pins_dpi) |
|---|
| 398 | + pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi); |
|---|
| 399 | + |
|---|
| 414 | 400 | return 0; |
|---|
| 415 | 401 | |
|---|
| 416 | 402 | err_pixel: |
|---|
| 417 | 403 | clk_disable_unprepare(dpi->engine_clk); |
|---|
| 418 | | -err_eng: |
|---|
| 419 | | - dpi->power_ctl &= ~pctl; |
|---|
| 404 | +err_refcount: |
|---|
| 405 | + dpi->refcount--; |
|---|
| 420 | 406 | return ret; |
|---|
| 421 | 407 | } |
|---|
| 422 | 408 | |
|---|
| .. | .. |
|---|
| 435 | 421 | unsigned int factor; |
|---|
| 436 | 422 | |
|---|
| 437 | 423 | /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */ |
|---|
| 438 | | - |
|---|
| 439 | | - if (mode->clock <= 27000) |
|---|
| 440 | | - factor = 3 << 4; |
|---|
| 441 | | - else if (mode->clock <= 84000) |
|---|
| 442 | | - factor = 3 << 3; |
|---|
| 443 | | - else if (mode->clock <= 167000) |
|---|
| 444 | | - factor = 3 << 2; |
|---|
| 445 | | - else |
|---|
| 446 | | - factor = 3 << 1; |
|---|
| 424 | + factor = dpi->conf->cal_factor(mode->clock); |
|---|
| 447 | 425 | drm_display_mode_to_videomode(mode, &vm); |
|---|
| 448 | 426 | pll_rate = vm.pixelclock * factor; |
|---|
| 449 | 427 | |
|---|
| .. | .. |
|---|
| 518 | 496 | mtk_dpi_config_yc_map(dpi, dpi->yc_map); |
|---|
| 519 | 497 | mtk_dpi_config_color_format(dpi, dpi->color_format); |
|---|
| 520 | 498 | mtk_dpi_config_2n_h_fre(dpi); |
|---|
| 499 | + mtk_dpi_config_disable_edge(dpi); |
|---|
| 521 | 500 | mtk_dpi_sw_reset(dpi, false); |
|---|
| 522 | 501 | |
|---|
| 523 | 502 | return 0; |
|---|
| 524 | 503 | } |
|---|
| 525 | 504 | |
|---|
| 526 | | -static void mtk_dpi_encoder_destroy(struct drm_encoder *encoder) |
|---|
| 505 | +static int mtk_dpi_bridge_attach(struct drm_bridge *bridge, |
|---|
| 506 | + enum drm_bridge_attach_flags flags) |
|---|
| 527 | 507 | { |
|---|
| 528 | | - drm_encoder_cleanup(encoder); |
|---|
| 508 | + struct mtk_dpi *dpi = bridge_to_dpi(bridge); |
|---|
| 509 | + |
|---|
| 510 | + return drm_bridge_attach(bridge->encoder, dpi->next_bridge, |
|---|
| 511 | + &dpi->bridge, flags); |
|---|
| 529 | 512 | } |
|---|
| 530 | 513 | |
|---|
| 531 | | -static const struct drm_encoder_funcs mtk_dpi_encoder_funcs = { |
|---|
| 532 | | - .destroy = mtk_dpi_encoder_destroy, |
|---|
| 533 | | -}; |
|---|
| 534 | | - |
|---|
| 535 | | -static bool mtk_dpi_encoder_mode_fixup(struct drm_encoder *encoder, |
|---|
| 536 | | - const struct drm_display_mode *mode, |
|---|
| 537 | | - struct drm_display_mode *adjusted_mode) |
|---|
| 514 | +static void mtk_dpi_bridge_mode_set(struct drm_bridge *bridge, |
|---|
| 515 | + const struct drm_display_mode *mode, |
|---|
| 516 | + const struct drm_display_mode *adjusted_mode) |
|---|
| 538 | 517 | { |
|---|
| 539 | | - return true; |
|---|
| 540 | | -} |
|---|
| 541 | | - |
|---|
| 542 | | -static void mtk_dpi_encoder_mode_set(struct drm_encoder *encoder, |
|---|
| 543 | | - struct drm_display_mode *mode, |
|---|
| 544 | | - struct drm_display_mode *adjusted_mode) |
|---|
| 545 | | -{ |
|---|
| 546 | | - struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); |
|---|
| 518 | + struct mtk_dpi *dpi = bridge_to_dpi(bridge); |
|---|
| 547 | 519 | |
|---|
| 548 | 520 | drm_mode_copy(&dpi->mode, adjusted_mode); |
|---|
| 549 | 521 | } |
|---|
| 550 | 522 | |
|---|
| 551 | | -static void mtk_dpi_encoder_disable(struct drm_encoder *encoder) |
|---|
| 523 | +static void mtk_dpi_bridge_disable(struct drm_bridge *bridge) |
|---|
| 552 | 524 | { |
|---|
| 553 | | - struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); |
|---|
| 525 | + struct mtk_dpi *dpi = bridge_to_dpi(bridge); |
|---|
| 554 | 526 | |
|---|
| 555 | | - mtk_dpi_power_off(dpi, DPI_POWER_ENABLE); |
|---|
| 527 | + mtk_dpi_power_off(dpi); |
|---|
| 556 | 528 | } |
|---|
| 557 | 529 | |
|---|
| 558 | | -static void mtk_dpi_encoder_enable(struct drm_encoder *encoder) |
|---|
| 530 | +static void mtk_dpi_bridge_enable(struct drm_bridge *bridge) |
|---|
| 559 | 531 | { |
|---|
| 560 | | - struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); |
|---|
| 532 | + struct mtk_dpi *dpi = bridge_to_dpi(bridge); |
|---|
| 561 | 533 | |
|---|
| 562 | | - mtk_dpi_power_on(dpi, DPI_POWER_ENABLE); |
|---|
| 534 | + mtk_dpi_power_on(dpi); |
|---|
| 563 | 535 | mtk_dpi_set_display_mode(dpi, &dpi->mode); |
|---|
| 536 | + mtk_dpi_enable(dpi); |
|---|
| 564 | 537 | } |
|---|
| 565 | 538 | |
|---|
| 566 | | -static int mtk_dpi_atomic_check(struct drm_encoder *encoder, |
|---|
| 567 | | - struct drm_crtc_state *crtc_state, |
|---|
| 568 | | - struct drm_connector_state *conn_state) |
|---|
| 569 | | -{ |
|---|
| 570 | | - return 0; |
|---|
| 571 | | -} |
|---|
| 572 | | - |
|---|
| 573 | | -static const struct drm_encoder_helper_funcs mtk_dpi_encoder_helper_funcs = { |
|---|
| 574 | | - .mode_fixup = mtk_dpi_encoder_mode_fixup, |
|---|
| 575 | | - .mode_set = mtk_dpi_encoder_mode_set, |
|---|
| 576 | | - .disable = mtk_dpi_encoder_disable, |
|---|
| 577 | | - .enable = mtk_dpi_encoder_enable, |
|---|
| 578 | | - .atomic_check = mtk_dpi_atomic_check, |
|---|
| 539 | +static const struct drm_bridge_funcs mtk_dpi_bridge_funcs = { |
|---|
| 540 | + .attach = mtk_dpi_bridge_attach, |
|---|
| 541 | + .mode_set = mtk_dpi_bridge_mode_set, |
|---|
| 542 | + .disable = mtk_dpi_bridge_disable, |
|---|
| 543 | + .enable = mtk_dpi_bridge_enable, |
|---|
| 579 | 544 | }; |
|---|
| 580 | 545 | |
|---|
| 581 | 546 | static void mtk_dpi_start(struct mtk_ddp_comp *comp) |
|---|
| 582 | 547 | { |
|---|
| 583 | 548 | struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp); |
|---|
| 584 | 549 | |
|---|
| 585 | | - mtk_dpi_power_on(dpi, DPI_POWER_START); |
|---|
| 550 | + mtk_dpi_power_on(dpi); |
|---|
| 586 | 551 | } |
|---|
| 587 | 552 | |
|---|
| 588 | 553 | static void mtk_dpi_stop(struct mtk_ddp_comp *comp) |
|---|
| 589 | 554 | { |
|---|
| 590 | 555 | struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp); |
|---|
| 591 | 556 | |
|---|
| 592 | | - mtk_dpi_power_off(dpi, DPI_POWER_START); |
|---|
| 557 | + mtk_dpi_power_off(dpi); |
|---|
| 593 | 558 | } |
|---|
| 594 | 559 | |
|---|
| 595 | 560 | static const struct mtk_ddp_comp_funcs mtk_dpi_funcs = { |
|---|
| .. | .. |
|---|
| 610 | 575 | return ret; |
|---|
| 611 | 576 | } |
|---|
| 612 | 577 | |
|---|
| 613 | | - ret = drm_encoder_init(drm_dev, &dpi->encoder, &mtk_dpi_encoder_funcs, |
|---|
| 614 | | - DRM_MODE_ENCODER_TMDS, NULL); |
|---|
| 578 | + ret = drm_simple_encoder_init(drm_dev, &dpi->encoder, |
|---|
| 579 | + DRM_MODE_ENCODER_TMDS); |
|---|
| 615 | 580 | if (ret) { |
|---|
| 616 | 581 | dev_err(dev, "Failed to initialize decoder: %d\n", ret); |
|---|
| 617 | 582 | goto err_unregister; |
|---|
| 618 | 583 | } |
|---|
| 619 | | - drm_encoder_helper_add(&dpi->encoder, &mtk_dpi_encoder_helper_funcs); |
|---|
| 620 | 584 | |
|---|
| 621 | | - /* Currently DPI0 is fixed to be driven by OVL1 */ |
|---|
| 622 | | - dpi->encoder.possible_crtcs = BIT(1); |
|---|
| 585 | + dpi->encoder.possible_crtcs = mtk_drm_find_possible_crtc_by_comp(drm_dev, dpi->ddp_comp); |
|---|
| 623 | 586 | |
|---|
| 624 | | - ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL); |
|---|
| 587 | + ret = drm_bridge_attach(&dpi->encoder, &dpi->bridge, NULL, 0); |
|---|
| 625 | 588 | if (ret) { |
|---|
| 626 | 589 | dev_err(dev, "Failed to attach bridge: %d\n", ret); |
|---|
| 627 | 590 | goto err_cleanup; |
|---|
| .. | .. |
|---|
| 656 | 619 | .unbind = mtk_dpi_unbind, |
|---|
| 657 | 620 | }; |
|---|
| 658 | 621 | |
|---|
| 622 | +static unsigned int mt8173_calculate_factor(int clock) |
|---|
| 623 | +{ |
|---|
| 624 | + if (clock <= 27000) |
|---|
| 625 | + return 3 << 4; |
|---|
| 626 | + else if (clock <= 84000) |
|---|
| 627 | + return 3 << 3; |
|---|
| 628 | + else if (clock <= 167000) |
|---|
| 629 | + return 3 << 2; |
|---|
| 630 | + else |
|---|
| 631 | + return 3 << 1; |
|---|
| 632 | +} |
|---|
| 633 | + |
|---|
| 634 | +static unsigned int mt2701_calculate_factor(int clock) |
|---|
| 635 | +{ |
|---|
| 636 | + if (clock <= 64000) |
|---|
| 637 | + return 4; |
|---|
| 638 | + else if (clock <= 128000) |
|---|
| 639 | + return 2; |
|---|
| 640 | + else |
|---|
| 641 | + return 1; |
|---|
| 642 | +} |
|---|
| 643 | + |
|---|
| 644 | +static unsigned int mt8183_calculate_factor(int clock) |
|---|
| 645 | +{ |
|---|
| 646 | + if (clock <= 27000) |
|---|
| 647 | + return 8; |
|---|
| 648 | + else if (clock <= 167000) |
|---|
| 649 | + return 4; |
|---|
| 650 | + else |
|---|
| 651 | + return 2; |
|---|
| 652 | +} |
|---|
| 653 | + |
|---|
| 654 | +static const struct mtk_dpi_conf mt8173_conf = { |
|---|
| 655 | + .cal_factor = mt8173_calculate_factor, |
|---|
| 656 | + .reg_h_fre_con = 0xe0, |
|---|
| 657 | +}; |
|---|
| 658 | + |
|---|
| 659 | +static const struct mtk_dpi_conf mt2701_conf = { |
|---|
| 660 | + .cal_factor = mt2701_calculate_factor, |
|---|
| 661 | + .reg_h_fre_con = 0xb0, |
|---|
| 662 | + .edge_sel_en = true, |
|---|
| 663 | +}; |
|---|
| 664 | + |
|---|
| 665 | +static const struct mtk_dpi_conf mt8183_conf = { |
|---|
| 666 | + .cal_factor = mt8183_calculate_factor, |
|---|
| 667 | + .reg_h_fre_con = 0xe0, |
|---|
| 668 | +}; |
|---|
| 669 | + |
|---|
| 659 | 670 | static int mtk_dpi_probe(struct platform_device *pdev) |
|---|
| 660 | 671 | { |
|---|
| 661 | 672 | struct device *dev = &pdev->dev; |
|---|
| 662 | 673 | struct mtk_dpi *dpi; |
|---|
| 663 | 674 | struct resource *mem; |
|---|
| 664 | | - struct device_node *bridge_node; |
|---|
| 665 | 675 | int comp_id; |
|---|
| 666 | 676 | int ret; |
|---|
| 667 | 677 | |
|---|
| .. | .. |
|---|
| 670 | 680 | return -ENOMEM; |
|---|
| 671 | 681 | |
|---|
| 672 | 682 | dpi->dev = dev; |
|---|
| 683 | + dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev); |
|---|
| 673 | 684 | |
|---|
| 685 | + dpi->pinctrl = devm_pinctrl_get(&pdev->dev); |
|---|
| 686 | + if (IS_ERR(dpi->pinctrl)) { |
|---|
| 687 | + dpi->pinctrl = NULL; |
|---|
| 688 | + dev_dbg(&pdev->dev, "Cannot find pinctrl!\n"); |
|---|
| 689 | + } |
|---|
| 690 | + if (dpi->pinctrl) { |
|---|
| 691 | + dpi->pins_gpio = pinctrl_lookup_state(dpi->pinctrl, "sleep"); |
|---|
| 692 | + if (IS_ERR(dpi->pins_gpio)) { |
|---|
| 693 | + dpi->pins_gpio = NULL; |
|---|
| 694 | + dev_dbg(&pdev->dev, "Cannot find pinctrl idle!\n"); |
|---|
| 695 | + } |
|---|
| 696 | + if (dpi->pins_gpio) |
|---|
| 697 | + pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio); |
|---|
| 698 | + |
|---|
| 699 | + dpi->pins_dpi = pinctrl_lookup_state(dpi->pinctrl, "default"); |
|---|
| 700 | + if (IS_ERR(dpi->pins_dpi)) { |
|---|
| 701 | + dpi->pins_dpi = NULL; |
|---|
| 702 | + dev_dbg(&pdev->dev, "Cannot find pinctrl active!\n"); |
|---|
| 703 | + } |
|---|
| 704 | + } |
|---|
| 674 | 705 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 675 | 706 | dpi->regs = devm_ioremap_resource(dev, mem); |
|---|
| 676 | 707 | if (IS_ERR(dpi->regs)) { |
|---|
| .. | .. |
|---|
| 682 | 713 | dpi->engine_clk = devm_clk_get(dev, "engine"); |
|---|
| 683 | 714 | if (IS_ERR(dpi->engine_clk)) { |
|---|
| 684 | 715 | ret = PTR_ERR(dpi->engine_clk); |
|---|
| 685 | | - dev_err(dev, "Failed to get engine clock: %d\n", ret); |
|---|
| 716 | + if (ret != -EPROBE_DEFER) |
|---|
| 717 | + dev_err(dev, "Failed to get engine clock: %d\n", ret); |
|---|
| 718 | + |
|---|
| 686 | 719 | return ret; |
|---|
| 687 | 720 | } |
|---|
| 688 | 721 | |
|---|
| 689 | 722 | dpi->pixel_clk = devm_clk_get(dev, "pixel"); |
|---|
| 690 | 723 | if (IS_ERR(dpi->pixel_clk)) { |
|---|
| 691 | 724 | ret = PTR_ERR(dpi->pixel_clk); |
|---|
| 692 | | - dev_err(dev, "Failed to get pixel clock: %d\n", ret); |
|---|
| 725 | + if (ret != -EPROBE_DEFER) |
|---|
| 726 | + dev_err(dev, "Failed to get pixel clock: %d\n", ret); |
|---|
| 727 | + |
|---|
| 693 | 728 | return ret; |
|---|
| 694 | 729 | } |
|---|
| 695 | 730 | |
|---|
| 696 | 731 | dpi->tvd_clk = devm_clk_get(dev, "pll"); |
|---|
| 697 | 732 | if (IS_ERR(dpi->tvd_clk)) { |
|---|
| 698 | 733 | ret = PTR_ERR(dpi->tvd_clk); |
|---|
| 699 | | - dev_err(dev, "Failed to get tvdpll clock: %d\n", ret); |
|---|
| 734 | + if (ret != -EPROBE_DEFER) |
|---|
| 735 | + dev_err(dev, "Failed to get tvdpll clock: %d\n", ret); |
|---|
| 736 | + |
|---|
| 700 | 737 | return ret; |
|---|
| 701 | 738 | } |
|---|
| 702 | 739 | |
|---|
| .. | .. |
|---|
| 706 | 743 | return -EINVAL; |
|---|
| 707 | 744 | } |
|---|
| 708 | 745 | |
|---|
| 709 | | - bridge_node = of_graph_get_remote_node(dev->of_node, 0, 0); |
|---|
| 710 | | - if (!bridge_node) |
|---|
| 711 | | - return -ENODEV; |
|---|
| 746 | + ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, |
|---|
| 747 | + NULL, &dpi->next_bridge); |
|---|
| 748 | + if (ret) |
|---|
| 749 | + return ret; |
|---|
| 712 | 750 | |
|---|
| 713 | | - dev_info(dev, "Found bridge node: %pOF\n", bridge_node); |
|---|
| 714 | | - |
|---|
| 715 | | - dpi->bridge = of_drm_find_bridge(bridge_node); |
|---|
| 716 | | - of_node_put(bridge_node); |
|---|
| 717 | | - if (!dpi->bridge) |
|---|
| 718 | | - return -EPROBE_DEFER; |
|---|
| 751 | + dev_info(dev, "Found bridge node: %pOF\n", dpi->next_bridge->of_node); |
|---|
| 719 | 752 | |
|---|
| 720 | 753 | comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI); |
|---|
| 721 | 754 | if (comp_id < 0) { |
|---|
| .. | .. |
|---|
| 732 | 765 | |
|---|
| 733 | 766 | platform_set_drvdata(pdev, dpi); |
|---|
| 734 | 767 | |
|---|
| 768 | + dpi->bridge.funcs = &mtk_dpi_bridge_funcs; |
|---|
| 769 | + dpi->bridge.of_node = dev->of_node; |
|---|
| 770 | + dpi->bridge.type = DRM_MODE_CONNECTOR_DPI; |
|---|
| 771 | + |
|---|
| 772 | + drm_bridge_add(&dpi->bridge); |
|---|
| 773 | + |
|---|
| 735 | 774 | ret = component_add(dev, &mtk_dpi_component_ops); |
|---|
| 736 | 775 | if (ret) { |
|---|
| 776 | + drm_bridge_remove(&dpi->bridge); |
|---|
| 737 | 777 | dev_err(dev, "Failed to add component: %d\n", ret); |
|---|
| 738 | 778 | return ret; |
|---|
| 739 | 779 | } |
|---|
| .. | .. |
|---|
| 743 | 783 | |
|---|
| 744 | 784 | static int mtk_dpi_remove(struct platform_device *pdev) |
|---|
| 745 | 785 | { |
|---|
| 786 | + struct mtk_dpi *dpi = platform_get_drvdata(pdev); |
|---|
| 787 | + |
|---|
| 746 | 788 | component_del(&pdev->dev, &mtk_dpi_component_ops); |
|---|
| 789 | + drm_bridge_remove(&dpi->bridge); |
|---|
| 747 | 790 | |
|---|
| 748 | 791 | return 0; |
|---|
| 749 | 792 | } |
|---|
| 750 | 793 | |
|---|
| 751 | 794 | static const struct of_device_id mtk_dpi_of_ids[] = { |
|---|
| 752 | | - { .compatible = "mediatek,mt8173-dpi", }, |
|---|
| 753 | | - {} |
|---|
| 795 | + { .compatible = "mediatek,mt2701-dpi", |
|---|
| 796 | + .data = &mt2701_conf, |
|---|
| 797 | + }, |
|---|
| 798 | + { .compatible = "mediatek,mt8173-dpi", |
|---|
| 799 | + .data = &mt8173_conf, |
|---|
| 800 | + }, |
|---|
| 801 | + { .compatible = "mediatek,mt8183-dpi", |
|---|
| 802 | + .data = &mt8183_conf, |
|---|
| 803 | + }, |
|---|
| 804 | + { }, |
|---|
| 754 | 805 | }; |
|---|
| 755 | 806 | |
|---|
| 756 | 807 | struct platform_driver mtk_dpi_driver = { |
|---|