Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.6-rc2 783 lines 20 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2014 MediaTek Inc. 4 * Author: Jie Qiu <jie.qiu@mediatek.com> 5 */ 6 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_graph.h> 14#include <linux/platform_device.h> 15#include <linux/types.h> 16 17#include <video/videomode.h> 18 19#include <drm/drm_atomic_helper.h> 20#include <drm/drm_bridge.h> 21#include <drm/drm_crtc.h> 22#include <drm/drm_of.h> 23 24#include "mtk_dpi_regs.h" 25#include "mtk_drm_ddp_comp.h" 26 27enum mtk_dpi_out_bit_num { 28 MTK_DPI_OUT_BIT_NUM_8BITS, 29 MTK_DPI_OUT_BIT_NUM_10BITS, 30 MTK_DPI_OUT_BIT_NUM_12BITS, 31 MTK_DPI_OUT_BIT_NUM_16BITS 32}; 33 34enum mtk_dpi_out_yc_map { 35 MTK_DPI_OUT_YC_MAP_RGB, 36 MTK_DPI_OUT_YC_MAP_CYCY, 37 MTK_DPI_OUT_YC_MAP_YCYC, 38 MTK_DPI_OUT_YC_MAP_CY, 39 MTK_DPI_OUT_YC_MAP_YC 40}; 41 42enum mtk_dpi_out_channel_swap { 43 MTK_DPI_OUT_CHANNEL_SWAP_RGB, 44 MTK_DPI_OUT_CHANNEL_SWAP_GBR, 45 MTK_DPI_OUT_CHANNEL_SWAP_BRG, 46 MTK_DPI_OUT_CHANNEL_SWAP_RBG, 47 MTK_DPI_OUT_CHANNEL_SWAP_GRB, 48 MTK_DPI_OUT_CHANNEL_SWAP_BGR 49}; 50 51enum mtk_dpi_out_color_format { 52 MTK_DPI_COLOR_FORMAT_RGB, 53 MTK_DPI_COLOR_FORMAT_RGB_FULL, 54 MTK_DPI_COLOR_FORMAT_YCBCR_444, 55 MTK_DPI_COLOR_FORMAT_YCBCR_422, 56 MTK_DPI_COLOR_FORMAT_XV_YCC, 57 MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL, 58 MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL 59}; 60 61struct mtk_dpi { 62 struct mtk_ddp_comp ddp_comp; 63 struct drm_encoder encoder; 64 struct drm_bridge *bridge; 65 void __iomem *regs; 66 struct device *dev; 67 struct clk *engine_clk; 68 struct clk *pixel_clk; 69 struct clk *tvd_clk; 70 int irq; 71 struct drm_display_mode mode; 72 const struct mtk_dpi_conf *conf; 73 enum mtk_dpi_out_color_format color_format; 74 enum mtk_dpi_out_yc_map yc_map; 75 enum mtk_dpi_out_bit_num bit_num; 76 enum mtk_dpi_out_channel_swap channel_swap; 77 int refcount; 78}; 79 80static inline struct mtk_dpi *mtk_dpi_from_encoder(struct drm_encoder *e) 81{ 82 return container_of(e, struct mtk_dpi, encoder); 83} 84 85enum mtk_dpi_polarity { 86 MTK_DPI_POLARITY_RISING, 87 MTK_DPI_POLARITY_FALLING, 88}; 89 90struct mtk_dpi_polarities { 91 enum mtk_dpi_polarity de_pol; 92 enum mtk_dpi_polarity ck_pol; 93 enum mtk_dpi_polarity hsync_pol; 94 enum mtk_dpi_polarity vsync_pol; 95}; 96 97struct mtk_dpi_sync_param { 98 u32 sync_width; 99 u32 front_porch; 100 u32 back_porch; 101 bool shift_half_line; 102}; 103 104struct mtk_dpi_yc_limit { 105 u16 y_top; 106 u16 y_bottom; 107 u16 c_top; 108 u16 c_bottom; 109}; 110 111struct mtk_dpi_conf { 112 unsigned int (*cal_factor)(int clock); 113 u32 reg_h_fre_con; 114 bool edge_sel_en; 115}; 116 117static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) 118{ 119 u32 tmp = readl(dpi->regs + offset) & ~mask; 120 121 tmp |= (val & mask); 122 writel(tmp, dpi->regs + offset); 123} 124 125static void mtk_dpi_sw_reset(struct mtk_dpi *dpi, bool reset) 126{ 127 mtk_dpi_mask(dpi, DPI_RET, reset ? RST : 0, RST); 128} 129 130static void mtk_dpi_enable(struct mtk_dpi *dpi) 131{ 132 mtk_dpi_mask(dpi, DPI_EN, EN, EN); 133} 134 135static void mtk_dpi_disable(struct mtk_dpi *dpi) 136{ 137 mtk_dpi_mask(dpi, DPI_EN, 0, EN); 138} 139 140static void mtk_dpi_config_hsync(struct mtk_dpi *dpi, 141 struct mtk_dpi_sync_param *sync) 142{ 143 mtk_dpi_mask(dpi, DPI_TGEN_HWIDTH, 144 sync->sync_width << HPW, HPW_MASK); 145 mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, 146 sync->back_porch << HBP, HBP_MASK); 147 mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, sync->front_porch << HFP, 148 HFP_MASK); 149} 150 151static void mtk_dpi_config_vsync(struct mtk_dpi *dpi, 152 struct mtk_dpi_sync_param *sync, 153 u32 width_addr, u32 porch_addr) 154{ 155 mtk_dpi_mask(dpi, width_addr, 156 sync->sync_width << VSYNC_WIDTH_SHIFT, 157 VSYNC_WIDTH_MASK); 158 mtk_dpi_mask(dpi, width_addr, 159 sync->shift_half_line << VSYNC_HALF_LINE_SHIFT, 160 VSYNC_HALF_LINE_MASK); 161 mtk_dpi_mask(dpi, porch_addr, 162 sync->back_porch << VSYNC_BACK_PORCH_SHIFT, 163 VSYNC_BACK_PORCH_MASK); 164 mtk_dpi_mask(dpi, porch_addr, 165 sync->front_porch << VSYNC_FRONT_PORCH_SHIFT, 166 VSYNC_FRONT_PORCH_MASK); 167} 168 169static void mtk_dpi_config_vsync_lodd(struct mtk_dpi *dpi, 170 struct mtk_dpi_sync_param *sync) 171{ 172 mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH, DPI_TGEN_VPORCH); 173} 174 175static void mtk_dpi_config_vsync_leven(struct mtk_dpi *dpi, 176 struct mtk_dpi_sync_param *sync) 177{ 178 mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_LEVEN, 179 DPI_TGEN_VPORCH_LEVEN); 180} 181 182static void mtk_dpi_config_vsync_rodd(struct mtk_dpi *dpi, 183 struct mtk_dpi_sync_param *sync) 184{ 185 mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_RODD, 186 DPI_TGEN_VPORCH_RODD); 187} 188 189static void mtk_dpi_config_vsync_reven(struct mtk_dpi *dpi, 190 struct mtk_dpi_sync_param *sync) 191{ 192 mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_REVEN, 193 DPI_TGEN_VPORCH_REVEN); 194} 195 196static void mtk_dpi_config_pol(struct mtk_dpi *dpi, 197 struct mtk_dpi_polarities *dpi_pol) 198{ 199 unsigned int pol; 200 201 pol = (dpi_pol->ck_pol == MTK_DPI_POLARITY_RISING ? 0 : CK_POL) | 202 (dpi_pol->de_pol == MTK_DPI_POLARITY_RISING ? 0 : DE_POL) | 203 (dpi_pol->hsync_pol == MTK_DPI_POLARITY_RISING ? 0 : HSYNC_POL) | 204 (dpi_pol->vsync_pol == MTK_DPI_POLARITY_RISING ? 0 : VSYNC_POL); 205 mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, pol, 206 CK_POL | DE_POL | HSYNC_POL | VSYNC_POL); 207} 208 209static void mtk_dpi_config_3d(struct mtk_dpi *dpi, bool en_3d) 210{ 211 mtk_dpi_mask(dpi, DPI_CON, en_3d ? TDFP_EN : 0, TDFP_EN); 212} 213 214static void mtk_dpi_config_interface(struct mtk_dpi *dpi, bool inter) 215{ 216 mtk_dpi_mask(dpi, DPI_CON, inter ? INTL_EN : 0, INTL_EN); 217} 218 219static void mtk_dpi_config_fb_size(struct mtk_dpi *dpi, u32 width, u32 height) 220{ 221 mtk_dpi_mask(dpi, DPI_SIZE, width << HSIZE, HSIZE_MASK); 222 mtk_dpi_mask(dpi, DPI_SIZE, height << VSIZE, VSIZE_MASK); 223} 224 225static void mtk_dpi_config_channel_limit(struct mtk_dpi *dpi, 226 struct mtk_dpi_yc_limit *limit) 227{ 228 mtk_dpi_mask(dpi, DPI_Y_LIMIT, limit->y_bottom << Y_LIMINT_BOT, 229 Y_LIMINT_BOT_MASK); 230 mtk_dpi_mask(dpi, DPI_Y_LIMIT, limit->y_top << Y_LIMINT_TOP, 231 Y_LIMINT_TOP_MASK); 232 mtk_dpi_mask(dpi, DPI_C_LIMIT, limit->c_bottom << C_LIMIT_BOT, 233 C_LIMIT_BOT_MASK); 234 mtk_dpi_mask(dpi, DPI_C_LIMIT, limit->c_top << C_LIMIT_TOP, 235 C_LIMIT_TOP_MASK); 236} 237 238static void mtk_dpi_config_bit_num(struct mtk_dpi *dpi, 239 enum mtk_dpi_out_bit_num num) 240{ 241 u32 val; 242 243 switch (num) { 244 case MTK_DPI_OUT_BIT_NUM_8BITS: 245 val = OUT_BIT_8; 246 break; 247 case MTK_DPI_OUT_BIT_NUM_10BITS: 248 val = OUT_BIT_10; 249 break; 250 case MTK_DPI_OUT_BIT_NUM_12BITS: 251 val = OUT_BIT_12; 252 break; 253 case MTK_DPI_OUT_BIT_NUM_16BITS: 254 val = OUT_BIT_16; 255 break; 256 default: 257 val = OUT_BIT_8; 258 break; 259 } 260 mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << OUT_BIT, 261 OUT_BIT_MASK); 262} 263 264static void mtk_dpi_config_yc_map(struct mtk_dpi *dpi, 265 enum mtk_dpi_out_yc_map map) 266{ 267 u32 val; 268 269 switch (map) { 270 case MTK_DPI_OUT_YC_MAP_RGB: 271 val = YC_MAP_RGB; 272 break; 273 case MTK_DPI_OUT_YC_MAP_CYCY: 274 val = YC_MAP_CYCY; 275 break; 276 case MTK_DPI_OUT_YC_MAP_YCYC: 277 val = YC_MAP_YCYC; 278 break; 279 case MTK_DPI_OUT_YC_MAP_CY: 280 val = YC_MAP_CY; 281 break; 282 case MTK_DPI_OUT_YC_MAP_YC: 283 val = YC_MAP_YC; 284 break; 285 default: 286 val = YC_MAP_RGB; 287 break; 288 } 289 290 mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << YC_MAP, YC_MAP_MASK); 291} 292 293static void mtk_dpi_config_channel_swap(struct mtk_dpi *dpi, 294 enum mtk_dpi_out_channel_swap swap) 295{ 296 u32 val; 297 298 switch (swap) { 299 case MTK_DPI_OUT_CHANNEL_SWAP_RGB: 300 val = SWAP_RGB; 301 break; 302 case MTK_DPI_OUT_CHANNEL_SWAP_GBR: 303 val = SWAP_GBR; 304 break; 305 case MTK_DPI_OUT_CHANNEL_SWAP_BRG: 306 val = SWAP_BRG; 307 break; 308 case MTK_DPI_OUT_CHANNEL_SWAP_RBG: 309 val = SWAP_RBG; 310 break; 311 case MTK_DPI_OUT_CHANNEL_SWAP_GRB: 312 val = SWAP_GRB; 313 break; 314 case MTK_DPI_OUT_CHANNEL_SWAP_BGR: 315 val = SWAP_BGR; 316 break; 317 default: 318 val = SWAP_RGB; 319 break; 320 } 321 322 mtk_dpi_mask(dpi, DPI_OUTPUT_SETTING, val << CH_SWAP, CH_SWAP_MASK); 323} 324 325static void mtk_dpi_config_yuv422_enable(struct mtk_dpi *dpi, bool enable) 326{ 327 mtk_dpi_mask(dpi, DPI_CON, enable ? YUV422_EN : 0, YUV422_EN); 328} 329 330static void mtk_dpi_config_csc_enable(struct mtk_dpi *dpi, bool enable) 331{ 332 mtk_dpi_mask(dpi, DPI_CON, enable ? CSC_ENABLE : 0, CSC_ENABLE); 333} 334 335static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable) 336{ 337 mtk_dpi_mask(dpi, DPI_CON, enable ? IN_RB_SWAP : 0, IN_RB_SWAP); 338} 339 340static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi) 341{ 342 mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N); 343} 344 345static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi) 346{ 347 if (dpi->conf->edge_sel_en) 348 mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN); 349} 350 351static void mtk_dpi_config_color_format(struct mtk_dpi *dpi, 352 enum mtk_dpi_out_color_format format) 353{ 354 if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_444) || 355 (format == MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL)) { 356 mtk_dpi_config_yuv422_enable(dpi, false); 357 mtk_dpi_config_csc_enable(dpi, true); 358 mtk_dpi_config_swap_input(dpi, false); 359 mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_BGR); 360 } else if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_422) || 361 (format == MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL)) { 362 mtk_dpi_config_yuv422_enable(dpi, true); 363 mtk_dpi_config_csc_enable(dpi, true); 364 mtk_dpi_config_swap_input(dpi, true); 365 mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB); 366 } else { 367 mtk_dpi_config_yuv422_enable(dpi, false); 368 mtk_dpi_config_csc_enable(dpi, false); 369 mtk_dpi_config_swap_input(dpi, false); 370 mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB); 371 } 372} 373 374static void mtk_dpi_power_off(struct mtk_dpi *dpi) 375{ 376 if (WARN_ON(dpi->refcount == 0)) 377 return; 378 379 if (--dpi->refcount != 0) 380 return; 381 382 mtk_dpi_disable(dpi); 383 clk_disable_unprepare(dpi->pixel_clk); 384 clk_disable_unprepare(dpi->engine_clk); 385} 386 387static int mtk_dpi_power_on(struct mtk_dpi *dpi) 388{ 389 int ret; 390 391 if (++dpi->refcount != 1) 392 return 0; 393 394 ret = clk_prepare_enable(dpi->engine_clk); 395 if (ret) { 396 dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret); 397 goto err_refcount; 398 } 399 400 ret = clk_prepare_enable(dpi->pixel_clk); 401 if (ret) { 402 dev_err(dpi->dev, "Failed to enable pixel clock: %d\n", ret); 403 goto err_pixel; 404 } 405 406 mtk_dpi_enable(dpi); 407 return 0; 408 409err_pixel: 410 clk_disable_unprepare(dpi->engine_clk); 411err_refcount: 412 dpi->refcount--; 413 return ret; 414} 415 416static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, 417 struct drm_display_mode *mode) 418{ 419 struct mtk_dpi_yc_limit limit; 420 struct mtk_dpi_polarities dpi_pol; 421 struct mtk_dpi_sync_param hsync; 422 struct mtk_dpi_sync_param vsync_lodd = { 0 }; 423 struct mtk_dpi_sync_param vsync_leven = { 0 }; 424 struct mtk_dpi_sync_param vsync_rodd = { 0 }; 425 struct mtk_dpi_sync_param vsync_reven = { 0 }; 426 struct videomode vm = { 0 }; 427 unsigned long pll_rate; 428 unsigned int factor; 429 430 /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */ 431 factor = dpi->conf->cal_factor(mode->clock); 432 drm_display_mode_to_videomode(mode, &vm); 433 pll_rate = vm.pixelclock * factor; 434 435 dev_dbg(dpi->dev, "Want PLL %lu Hz, pixel clock %lu Hz\n", 436 pll_rate, vm.pixelclock); 437 438 clk_set_rate(dpi->tvd_clk, pll_rate); 439 pll_rate = clk_get_rate(dpi->tvd_clk); 440 441 vm.pixelclock = pll_rate / factor; 442 clk_set_rate(dpi->pixel_clk, vm.pixelclock); 443 vm.pixelclock = clk_get_rate(dpi->pixel_clk); 444 445 dev_dbg(dpi->dev, "Got PLL %lu Hz, pixel clock %lu Hz\n", 446 pll_rate, vm.pixelclock); 447 448 limit.c_bottom = 0x0010; 449 limit.c_top = 0x0FE0; 450 limit.y_bottom = 0x0010; 451 limit.y_top = 0x0FE0; 452 453 dpi_pol.ck_pol = MTK_DPI_POLARITY_FALLING; 454 dpi_pol.de_pol = MTK_DPI_POLARITY_RISING; 455 dpi_pol.hsync_pol = vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ? 456 MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING; 457 dpi_pol.vsync_pol = vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? 458 MTK_DPI_POLARITY_FALLING : MTK_DPI_POLARITY_RISING; 459 hsync.sync_width = vm.hsync_len; 460 hsync.back_porch = vm.hback_porch; 461 hsync.front_porch = vm.hfront_porch; 462 hsync.shift_half_line = false; 463 vsync_lodd.sync_width = vm.vsync_len; 464 vsync_lodd.back_porch = vm.vback_porch; 465 vsync_lodd.front_porch = vm.vfront_porch; 466 vsync_lodd.shift_half_line = false; 467 468 if (vm.flags & DISPLAY_FLAGS_INTERLACED && 469 mode->flags & DRM_MODE_FLAG_3D_MASK) { 470 vsync_leven = vsync_lodd; 471 vsync_rodd = vsync_lodd; 472 vsync_reven = vsync_lodd; 473 vsync_leven.shift_half_line = true; 474 vsync_reven.shift_half_line = true; 475 } else if (vm.flags & DISPLAY_FLAGS_INTERLACED && 476 !(mode->flags & DRM_MODE_FLAG_3D_MASK)) { 477 vsync_leven = vsync_lodd; 478 vsync_leven.shift_half_line = true; 479 } else if (!(vm.flags & DISPLAY_FLAGS_INTERLACED) && 480 mode->flags & DRM_MODE_FLAG_3D_MASK) { 481 vsync_rodd = vsync_lodd; 482 } 483 mtk_dpi_sw_reset(dpi, true); 484 mtk_dpi_config_pol(dpi, &dpi_pol); 485 486 mtk_dpi_config_hsync(dpi, &hsync); 487 mtk_dpi_config_vsync_lodd(dpi, &vsync_lodd); 488 mtk_dpi_config_vsync_rodd(dpi, &vsync_rodd); 489 mtk_dpi_config_vsync_leven(dpi, &vsync_leven); 490 mtk_dpi_config_vsync_reven(dpi, &vsync_reven); 491 492 mtk_dpi_config_3d(dpi, !!(mode->flags & DRM_MODE_FLAG_3D_MASK)); 493 mtk_dpi_config_interface(dpi, !!(vm.flags & 494 DISPLAY_FLAGS_INTERLACED)); 495 if (vm.flags & DISPLAY_FLAGS_INTERLACED) 496 mtk_dpi_config_fb_size(dpi, vm.hactive, vm.vactive >> 1); 497 else 498 mtk_dpi_config_fb_size(dpi, vm.hactive, vm.vactive); 499 500 mtk_dpi_config_channel_limit(dpi, &limit); 501 mtk_dpi_config_bit_num(dpi, dpi->bit_num); 502 mtk_dpi_config_channel_swap(dpi, dpi->channel_swap); 503 mtk_dpi_config_yc_map(dpi, dpi->yc_map); 504 mtk_dpi_config_color_format(dpi, dpi->color_format); 505 mtk_dpi_config_2n_h_fre(dpi); 506 mtk_dpi_config_disable_edge(dpi); 507 mtk_dpi_sw_reset(dpi, false); 508 509 return 0; 510} 511 512static void mtk_dpi_encoder_destroy(struct drm_encoder *encoder) 513{ 514 drm_encoder_cleanup(encoder); 515} 516 517static const struct drm_encoder_funcs mtk_dpi_encoder_funcs = { 518 .destroy = mtk_dpi_encoder_destroy, 519}; 520 521static bool mtk_dpi_encoder_mode_fixup(struct drm_encoder *encoder, 522 const struct drm_display_mode *mode, 523 struct drm_display_mode *adjusted_mode) 524{ 525 return true; 526} 527 528static void mtk_dpi_encoder_mode_set(struct drm_encoder *encoder, 529 struct drm_display_mode *mode, 530 struct drm_display_mode *adjusted_mode) 531{ 532 struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); 533 534 drm_mode_copy(&dpi->mode, adjusted_mode); 535} 536 537static void mtk_dpi_encoder_disable(struct drm_encoder *encoder) 538{ 539 struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); 540 541 mtk_dpi_power_off(dpi); 542} 543 544static void mtk_dpi_encoder_enable(struct drm_encoder *encoder) 545{ 546 struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder); 547 548 mtk_dpi_power_on(dpi); 549 mtk_dpi_set_display_mode(dpi, &dpi->mode); 550} 551 552static int mtk_dpi_atomic_check(struct drm_encoder *encoder, 553 struct drm_crtc_state *crtc_state, 554 struct drm_connector_state *conn_state) 555{ 556 return 0; 557} 558 559static const struct drm_encoder_helper_funcs mtk_dpi_encoder_helper_funcs = { 560 .mode_fixup = mtk_dpi_encoder_mode_fixup, 561 .mode_set = mtk_dpi_encoder_mode_set, 562 .disable = mtk_dpi_encoder_disable, 563 .enable = mtk_dpi_encoder_enable, 564 .atomic_check = mtk_dpi_atomic_check, 565}; 566 567static void mtk_dpi_start(struct mtk_ddp_comp *comp) 568{ 569 struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp); 570 571 mtk_dpi_power_on(dpi); 572} 573 574static void mtk_dpi_stop(struct mtk_ddp_comp *comp) 575{ 576 struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp); 577 578 mtk_dpi_power_off(dpi); 579} 580 581static const struct mtk_ddp_comp_funcs mtk_dpi_funcs = { 582 .start = mtk_dpi_start, 583 .stop = mtk_dpi_stop, 584}; 585 586static int mtk_dpi_bind(struct device *dev, struct device *master, void *data) 587{ 588 struct mtk_dpi *dpi = dev_get_drvdata(dev); 589 struct drm_device *drm_dev = data; 590 int ret; 591 592 ret = mtk_ddp_comp_register(drm_dev, &dpi->ddp_comp); 593 if (ret < 0) { 594 dev_err(dev, "Failed to register component %pOF: %d\n", 595 dev->of_node, ret); 596 return ret; 597 } 598 599 ret = drm_encoder_init(drm_dev, &dpi->encoder, &mtk_dpi_encoder_funcs, 600 DRM_MODE_ENCODER_TMDS, NULL); 601 if (ret) { 602 dev_err(dev, "Failed to initialize decoder: %d\n", ret); 603 goto err_unregister; 604 } 605 drm_encoder_helper_add(&dpi->encoder, &mtk_dpi_encoder_helper_funcs); 606 607 /* Currently DPI0 is fixed to be driven by OVL1 */ 608 dpi->encoder.possible_crtcs = BIT(1); 609 610 ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL); 611 if (ret) { 612 dev_err(dev, "Failed to attach bridge: %d\n", ret); 613 goto err_cleanup; 614 } 615 616 dpi->bit_num = MTK_DPI_OUT_BIT_NUM_8BITS; 617 dpi->channel_swap = MTK_DPI_OUT_CHANNEL_SWAP_RGB; 618 dpi->yc_map = MTK_DPI_OUT_YC_MAP_RGB; 619 dpi->color_format = MTK_DPI_COLOR_FORMAT_RGB; 620 621 return 0; 622 623err_cleanup: 624 drm_encoder_cleanup(&dpi->encoder); 625err_unregister: 626 mtk_ddp_comp_unregister(drm_dev, &dpi->ddp_comp); 627 return ret; 628} 629 630static void mtk_dpi_unbind(struct device *dev, struct device *master, 631 void *data) 632{ 633 struct mtk_dpi *dpi = dev_get_drvdata(dev); 634 struct drm_device *drm_dev = data; 635 636 drm_encoder_cleanup(&dpi->encoder); 637 mtk_ddp_comp_unregister(drm_dev, &dpi->ddp_comp); 638} 639 640static const struct component_ops mtk_dpi_component_ops = { 641 .bind = mtk_dpi_bind, 642 .unbind = mtk_dpi_unbind, 643}; 644 645static unsigned int mt8173_calculate_factor(int clock) 646{ 647 if (clock <= 27000) 648 return 3 << 4; 649 else if (clock <= 84000) 650 return 3 << 3; 651 else if (clock <= 167000) 652 return 3 << 2; 653 else 654 return 3 << 1; 655} 656 657static unsigned int mt2701_calculate_factor(int clock) 658{ 659 if (clock <= 64000) 660 return 4; 661 else if (clock <= 128000) 662 return 2; 663 else 664 return 1; 665} 666 667static const struct mtk_dpi_conf mt8173_conf = { 668 .cal_factor = mt8173_calculate_factor, 669 .reg_h_fre_con = 0xe0, 670}; 671 672static const struct mtk_dpi_conf mt2701_conf = { 673 .cal_factor = mt2701_calculate_factor, 674 .reg_h_fre_con = 0xb0, 675 .edge_sel_en = true, 676}; 677 678static int mtk_dpi_probe(struct platform_device *pdev) 679{ 680 struct device *dev = &pdev->dev; 681 struct mtk_dpi *dpi; 682 struct resource *mem; 683 int comp_id; 684 int ret; 685 686 dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL); 687 if (!dpi) 688 return -ENOMEM; 689 690 dpi->dev = dev; 691 dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev); 692 693 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 694 dpi->regs = devm_ioremap_resource(dev, mem); 695 if (IS_ERR(dpi->regs)) { 696 ret = PTR_ERR(dpi->regs); 697 dev_err(dev, "Failed to ioremap mem resource: %d\n", ret); 698 return ret; 699 } 700 701 dpi->engine_clk = devm_clk_get(dev, "engine"); 702 if (IS_ERR(dpi->engine_clk)) { 703 ret = PTR_ERR(dpi->engine_clk); 704 dev_err(dev, "Failed to get engine clock: %d\n", ret); 705 return ret; 706 } 707 708 dpi->pixel_clk = devm_clk_get(dev, "pixel"); 709 if (IS_ERR(dpi->pixel_clk)) { 710 ret = PTR_ERR(dpi->pixel_clk); 711 dev_err(dev, "Failed to get pixel clock: %d\n", ret); 712 return ret; 713 } 714 715 dpi->tvd_clk = devm_clk_get(dev, "pll"); 716 if (IS_ERR(dpi->tvd_clk)) { 717 ret = PTR_ERR(dpi->tvd_clk); 718 dev_err(dev, "Failed to get tvdpll clock: %d\n", ret); 719 return ret; 720 } 721 722 dpi->irq = platform_get_irq(pdev, 0); 723 if (dpi->irq <= 0) { 724 dev_err(dev, "Failed to get irq: %d\n", dpi->irq); 725 return -EINVAL; 726 } 727 728 ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, 729 NULL, &dpi->bridge); 730 if (ret) 731 return ret; 732 733 dev_info(dev, "Found bridge node: %pOF\n", dpi->bridge->of_node); 734 735 comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI); 736 if (comp_id < 0) { 737 dev_err(dev, "Failed to identify by alias: %d\n", comp_id); 738 return comp_id; 739 } 740 741 ret = mtk_ddp_comp_init(dev, dev->of_node, &dpi->ddp_comp, comp_id, 742 &mtk_dpi_funcs); 743 if (ret) { 744 dev_err(dev, "Failed to initialize component: %d\n", ret); 745 return ret; 746 } 747 748 platform_set_drvdata(pdev, dpi); 749 750 ret = component_add(dev, &mtk_dpi_component_ops); 751 if (ret) { 752 dev_err(dev, "Failed to add component: %d\n", ret); 753 return ret; 754 } 755 756 return 0; 757} 758 759static int mtk_dpi_remove(struct platform_device *pdev) 760{ 761 component_del(&pdev->dev, &mtk_dpi_component_ops); 762 763 return 0; 764} 765 766static const struct of_device_id mtk_dpi_of_ids[] = { 767 { .compatible = "mediatek,mt2701-dpi", 768 .data = &mt2701_conf, 769 }, 770 { .compatible = "mediatek,mt8173-dpi", 771 .data = &mt8173_conf, 772 }, 773 { }, 774}; 775 776struct platform_driver mtk_dpi_driver = { 777 .probe = mtk_dpi_probe, 778 .remove = mtk_dpi_remove, 779 .driver = { 780 .name = "mediatek-dpi", 781 .of_match_table = mtk_dpi_of_ids, 782 }, 783};