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