814 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * RZ/G2L MIPI DSI Encoder Driver4 *5 * Copyright (C) 2022 Renesas Electronics Corporation6 */7#include <linux/clk.h>8#include <linux/delay.h>9#include <linux/io.h>10#include <linux/iopoll.h>11#include <linux/module.h>12#include <linux/of.h>13#include <linux/of_graph.h>14#include <linux/platform_device.h>15#include <linux/pm_runtime.h>16#include <linux/reset.h>17#include <linux/slab.h>18 19#include <drm/drm_atomic.h>20#include <drm/drm_atomic_helper.h>21#include <drm/drm_bridge.h>22#include <drm/drm_mipi_dsi.h>23#include <drm/drm_of.h>24#include <drm/drm_panel.h>25#include <drm/drm_probe_helper.h>26 27#include "rzg2l_mipi_dsi_regs.h"28 29struct rzg2l_mipi_dsi {30 struct device *dev;31 void __iomem *mmio;32 33 struct reset_control *rstc;34 struct reset_control *arstc;35 struct reset_control *prstc;36 37 struct mipi_dsi_host host;38 struct drm_bridge bridge;39 struct drm_bridge *next_bridge;40 41 struct clk *vclk;42 43 enum mipi_dsi_pixel_format format;44 unsigned int num_data_lanes;45 unsigned int lanes;46 unsigned long mode_flags;47};48 49static inline struct rzg2l_mipi_dsi *50bridge_to_rzg2l_mipi_dsi(struct drm_bridge *bridge)51{52 return container_of(bridge, struct rzg2l_mipi_dsi, bridge);53}54 55static inline struct rzg2l_mipi_dsi *56host_to_rzg2l_mipi_dsi(struct mipi_dsi_host *host)57{58 return container_of(host, struct rzg2l_mipi_dsi, host);59}60 61struct rzg2l_mipi_dsi_timings {62 unsigned long hsfreq_max;63 u32 t_init;64 u32 tclk_prepare;65 u32 ths_prepare;66 u32 tclk_zero;67 u32 tclk_pre;68 u32 tclk_post;69 u32 tclk_trail;70 u32 ths_zero;71 u32 ths_trail;72 u32 ths_exit;73 u32 tlpx;74};75 76static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = {77 {78 .hsfreq_max = 80000,79 .t_init = 79801,80 .tclk_prepare = 8,81 .ths_prepare = 13,82 .tclk_zero = 33,83 .tclk_pre = 24,84 .tclk_post = 94,85 .tclk_trail = 10,86 .ths_zero = 23,87 .ths_trail = 17,88 .ths_exit = 13,89 .tlpx = 6,90 },91 {92 .hsfreq_max = 125000,93 .t_init = 79801,94 .tclk_prepare = 8,95 .ths_prepare = 12,96 .tclk_zero = 33,97 .tclk_pre = 15,98 .tclk_post = 94,99 .tclk_trail = 10,100 .ths_zero = 23,101 .ths_trail = 17,102 .ths_exit = 13,103 .tlpx = 6,104 },105 {106 .hsfreq_max = 250000,107 .t_init = 79801,108 .tclk_prepare = 8,109 .ths_prepare = 12,110 .tclk_zero = 33,111 .tclk_pre = 13,112 .tclk_post = 94,113 .tclk_trail = 10,114 .ths_zero = 23,115 .ths_trail = 16,116 .ths_exit = 13,117 .tlpx = 6,118 },119 {120 .hsfreq_max = 360000,121 .t_init = 79801,122 .tclk_prepare = 8,123 .ths_prepare = 10,124 .tclk_zero = 33,125 .tclk_pre = 4,126 .tclk_post = 35,127 .tclk_trail = 7,128 .ths_zero = 16,129 .ths_trail = 9,130 .ths_exit = 13,131 .tlpx = 6,132 },133 {134 .hsfreq_max = 720000,135 .t_init = 79801,136 .tclk_prepare = 8,137 .ths_prepare = 9,138 .tclk_zero = 33,139 .tclk_pre = 4,140 .tclk_post = 35,141 .tclk_trail = 7,142 .ths_zero = 16,143 .ths_trail = 9,144 .ths_exit = 13,145 .tlpx = 6,146 },147 {148 .hsfreq_max = 1500000,149 .t_init = 79801,150 .tclk_prepare = 8,151 .ths_prepare = 9,152 .tclk_zero = 33,153 .tclk_pre = 4,154 .tclk_post = 35,155 .tclk_trail = 7,156 .ths_zero = 16,157 .ths_trail = 9,158 .ths_exit = 13,159 .tlpx = 6,160 },161};162 163static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)164{165 iowrite32(data, dsi->mmio + reg);166}167 168static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)169{170 iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg);171}172 173static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg)174{175 return ioread32(dsi->mmio + reg);176}177 178static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)179{180 return ioread32(dsi->mmio + LINK_REG_OFFSET + reg);181}182 183/* -----------------------------------------------------------------------------184 * Hardware Setup185 */186 187static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,188 unsigned long hsfreq)189{190 const struct rzg2l_mipi_dsi_timings *dphy_timings;191 unsigned int i;192 u32 dphyctrl0;193 u32 dphytim0;194 u32 dphytim1;195 u32 dphytim2;196 u32 dphytim3;197 int ret;198 199 /* All DSI global operation timings are set with recommended setting */200 for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) {201 dphy_timings = &rzg2l_mipi_dsi_global_timings[i];202 if (hsfreq <= dphy_timings->hsfreq_max)203 break;204 }205 206 /* Initializing DPHY before accessing LINK */207 dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN |208 DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR;209 210 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);211 usleep_range(20, 30);212 213 dphyctrl0 |= DSIDPHYCTRL0_EN_LDO1200;214 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);215 usleep_range(10, 20);216 217 dphytim0 = DSIDPHYTIM0_TCLK_MISS(0) |218 DSIDPHYTIM0_T_INIT(dphy_timings->t_init);219 dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) |220 DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) |221 DSIDPHYTIM1_THS_SETTLE(0) |222 DSIDPHYTIM1_TCLK_SETTLE(0);223 dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) |224 DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) |225 DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) |226 DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero);227 dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) |228 DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) |229 DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) |230 DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero);231 232 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0);233 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1);234 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2);235 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3);236 237 ret = reset_control_deassert(dsi->rstc);238 if (ret < 0)239 return ret;240 241 udelay(1);242 243 return 0;244}245 246static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi)247{248 u32 dphyctrl0;249 250 dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0);251 252 dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR);253 rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);254 255 reset_control_assert(dsi->rstc);256}257 258static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,259 const struct drm_display_mode *mode)260{261 unsigned long hsfreq;262 unsigned int bpp;263 u32 txsetr;264 u32 clstptsetr;265 u32 lptrnstsetr;266 u32 clkkpt;267 u32 clkbfht;268 u32 clkstpt;269 u32 golpbkt;270 int ret;271 272 /*273 * Relationship between hsclk and vclk must follow274 * vclk * bpp = hsclk * 8 * lanes275 * where vclk: video clock (Hz)276 * bpp: video pixel bit depth277 * hsclk: DSI HS Byte clock frequency (Hz)278 * lanes: number of data lanes279 *280 * hsclk(bit) = hsclk(byte) * 8281 */282 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);283 hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes);284 285 ret = pm_runtime_resume_and_get(dsi->dev);286 if (ret < 0)287 return ret;288 289 clk_set_rate(dsi->vclk, mode->clock * 1000);290 291 ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);292 if (ret < 0)293 goto err_phy;294 295 /* Enable Data lanes and Clock lanes */296 txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN;297 rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr);298 299 /*300 * Global timings characteristic depends on high speed Clock Frequency301 * Currently MIPI DSI-IF just supports maximum FHD@60 with:302 * - videoclock = 148.5 (MHz)303 * - bpp: maximum 24bpp304 * - data lanes: maximum 4 lanes305 * Therefore maximum hsclk will be 891 Mbps.306 */307 if (hsfreq > 445500) {308 clkkpt = 12;309 clkbfht = 15;310 clkstpt = 48;311 golpbkt = 75;312 } else if (hsfreq > 250000) {313 clkkpt = 7;314 clkbfht = 8;315 clkstpt = 27;316 golpbkt = 40;317 } else {318 clkkpt = 8;319 clkbfht = 6;320 clkstpt = 24;321 golpbkt = 29;322 }323 324 clstptsetr = CLSTPTSETR_CLKKPT(clkkpt) | CLSTPTSETR_CLKBFHT(clkbfht) |325 CLSTPTSETR_CLKSTPT(clkstpt);326 rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr);327 328 lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);329 rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);330 331 return 0;332 333err_phy:334 rzg2l_mipi_dsi_dphy_exit(dsi);335 pm_runtime_put(dsi->dev);336 337 return ret;338}339 340static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi)341{342 rzg2l_mipi_dsi_dphy_exit(dsi);343 pm_runtime_put(dsi->dev);344}345 346static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi,347 const struct drm_display_mode *mode)348{349 u32 vich1ppsetr;350 u32 vich1vssetr;351 u32 vich1vpsetr;352 u32 vich1hssetr;353 u32 vich1hpsetr;354 int dsi_format;355 u32 delay[2];356 u8 index;357 358 /* Configuration for Pixel Packet */359 dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format);360 switch (dsi_format) {361 case 24:362 vich1ppsetr = VICH1PPSETR_DT_RGB24;363 break;364 case 18:365 vich1ppsetr = VICH1PPSETR_DT_RGB18;366 break;367 }368 369 if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) &&370 !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST))371 vich1ppsetr |= VICH1PPSETR_TXESYNC_PULSE;372 373 rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr);374 375 /* Configuration for Video Parameters */376 vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) |377 VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start);378 vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ?379 VICH1VSSETR_VSPOL_HIGH : VICH1VSSETR_VSPOL_LOW;380 381 vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) |382 VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end);383 384 vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) |385 VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start);386 vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ?387 VICH1HSSETR_HSPOL_HIGH : VICH1HSSETR_HSPOL_LOW;388 389 vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) |390 VICH1HPSETR_HBP(mode->htotal - mode->hsync_end);391 392 rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr);393 rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr);394 rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr);395 rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr);396 397 /*398 * Configuration for Delay Value399 * Delay value based on 2 ranges of video clock.400 * 74.25MHz is videoclock of HD@60p or FHD@30p401 */402 if (mode->clock > 74250) {403 delay[0] = 231;404 delay[1] = 216;405 } else {406 delay[0] = 220;407 delay[1] = 212;408 }409 410 if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)411 index = 0;412 else413 index = 1;414 415 rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R,416 VICH1SET1R_DLY(delay[index]));417}418 419static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi)420{421 bool is_clk_cont;422 u32 hsclksetr;423 u32 status;424 int ret;425 426 is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);427 428 /* Start HS clock */429 hsclksetr = HSCLKSETR_HSCLKRUN_HS | (is_clk_cont ?430 HSCLKSETR_HSCLKMODE_CONT :431 HSCLKSETR_HSCLKMODE_NON_CONT);432 rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr);433 434 if (is_clk_cont) {435 ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,436 status & PLSR_CLLP2HS,437 2000, 20000, false, dsi, PLSR);438 if (ret < 0) {439 dev_err(dsi->dev, "failed to start HS clock\n");440 return ret;441 }442 }443 444 dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode",445 is_clk_cont ? "continuous" : "non-continuous");446 447 return 0;448}449 450static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi)451{452 bool is_clk_cont;453 u32 status;454 int ret;455 456 is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);457 458 /* Stop HS clock */459 rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR,460 is_clk_cont ? HSCLKSETR_HSCLKMODE_CONT :461 HSCLKSETR_HSCLKMODE_NON_CONT);462 463 if (is_clk_cont) {464 ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,465 status & PLSR_CLHS2LP,466 2000, 20000, false, dsi, PLSR);467 if (ret < 0) {468 dev_err(dsi->dev, "failed to stop HS clock\n");469 return ret;470 }471 }472 473 return 0;474}475 476static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi)477{478 u32 vich1set0r;479 u32 status;480 int ret;481 482 /* Configuration for Blanking sequence and start video input*/483 vich1set0r = VICH1SET0R_HFPNOLP | VICH1SET0R_HBPNOLP |484 VICH1SET0R_HSANOLP | VICH1SET0R_VSTART;485 rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r);486 487 ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,488 status & VICH1SR_VIRDY,489 2000, 20000, false, dsi, VICH1SR);490 if (ret < 0)491 dev_err(dsi->dev, "Failed to start video signal input\n");492 493 return ret;494}495 496static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi)497{498 u32 status;499 int ret;500 501 rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT);502 ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,503 (status & VICH1SR_STOP) && (!(status & VICH1SR_RUNNING)),504 2000, 20000, false, dsi, VICH1SR);505 if (ret < 0)506 goto err;507 508 ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,509 !(status & LINKSR_HSBUSY),510 2000, 20000, false, dsi, LINKSR);511 if (ret < 0)512 goto err;513 514 return 0;515 516err:517 dev_err(dsi->dev, "Failed to stop video signal input\n");518 return ret;519}520 521/* -----------------------------------------------------------------------------522 * Bridge523 */524 525static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge,526 enum drm_bridge_attach_flags flags)527{528 struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);529 530 return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge,531 flags);532}533 534static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,535 struct drm_bridge_state *old_bridge_state)536{537 struct drm_atomic_state *state = old_bridge_state->base.state;538 struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);539 const struct drm_display_mode *mode;540 struct drm_connector *connector;541 struct drm_crtc *crtc;542 int ret;543 544 connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);545 crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;546 mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;547 548 ret = rzg2l_mipi_dsi_startup(dsi, mode);549 if (ret < 0)550 return;551 552 rzg2l_mipi_dsi_set_display_timing(dsi, mode);553 554 ret = rzg2l_mipi_dsi_start_hs_clock(dsi);555 if (ret < 0)556 goto err_stop;557 558 ret = rzg2l_mipi_dsi_start_video(dsi);559 if (ret < 0)560 goto err_stop_clock;561 562 return;563 564err_stop_clock:565 rzg2l_mipi_dsi_stop_hs_clock(dsi);566err_stop:567 rzg2l_mipi_dsi_stop(dsi);568}569 570static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge,571 struct drm_bridge_state *old_bridge_state)572{573 struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);574 575 rzg2l_mipi_dsi_stop_video(dsi);576 rzg2l_mipi_dsi_stop_hs_clock(dsi);577 rzg2l_mipi_dsi_stop(dsi);578}579 580static enum drm_mode_status581rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,582 const struct drm_display_info *info,583 const struct drm_display_mode *mode)584{585 if (mode->clock > 148500)586 return MODE_CLOCK_HIGH;587 588 return MODE_OK;589}590 591static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = {592 .attach = rzg2l_mipi_dsi_attach,593 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,594 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,595 .atomic_reset = drm_atomic_helper_bridge_reset,596 .atomic_enable = rzg2l_mipi_dsi_atomic_enable,597 .atomic_disable = rzg2l_mipi_dsi_atomic_disable,598 .mode_valid = rzg2l_mipi_dsi_bridge_mode_valid,599};600 601/* -----------------------------------------------------------------------------602 * Host setting603 */604 605static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,606 struct mipi_dsi_device *device)607{608 struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);609 int ret;610 611 if (device->lanes > dsi->num_data_lanes) {612 dev_err(dsi->dev,613 "Number of lines of device (%u) exceeds host (%u)\n",614 device->lanes, dsi->num_data_lanes);615 return -EINVAL;616 }617 618 switch (mipi_dsi_pixel_format_to_bpp(device->format)) {619 case 24:620 case 18:621 break;622 default:623 dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format);624 return -EINVAL;625 }626 627 dsi->lanes = device->lanes;628 dsi->format = device->format;629 dsi->mode_flags = device->mode_flags;630 631 dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node,632 1, 0);633 if (IS_ERR(dsi->next_bridge)) {634 ret = PTR_ERR(dsi->next_bridge);635 dev_err(dsi->dev, "failed to get next bridge: %d\n", ret);636 return ret;637 }638 639 drm_bridge_add(&dsi->bridge);640 641 return 0;642}643 644static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,645 struct mipi_dsi_device *device)646{647 struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);648 649 drm_bridge_remove(&dsi->bridge);650 651 return 0;652}653 654static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {655 .attach = rzg2l_mipi_dsi_host_attach,656 .detach = rzg2l_mipi_dsi_host_detach,657};658 659/* -----------------------------------------------------------------------------660 * Power Management661 */662 663static int __maybe_unused rzg2l_mipi_pm_runtime_suspend(struct device *dev)664{665 struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);666 667 reset_control_assert(dsi->prstc);668 reset_control_assert(dsi->arstc);669 670 return 0;671}672 673static int __maybe_unused rzg2l_mipi_pm_runtime_resume(struct device *dev)674{675 struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);676 int ret;677 678 ret = reset_control_deassert(dsi->arstc);679 if (ret < 0)680 return ret;681 682 ret = reset_control_deassert(dsi->prstc);683 if (ret < 0)684 reset_control_assert(dsi->arstc);685 686 return ret;687}688 689static const struct dev_pm_ops rzg2l_mipi_pm_ops = {690 SET_RUNTIME_PM_OPS(rzg2l_mipi_pm_runtime_suspend, rzg2l_mipi_pm_runtime_resume, NULL)691};692 693/* -----------------------------------------------------------------------------694 * Probe & Remove695 */696 697static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)698{699 unsigned int num_data_lanes;700 struct rzg2l_mipi_dsi *dsi;701 u32 txsetr;702 int ret;703 704 dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);705 if (!dsi)706 return -ENOMEM;707 708 platform_set_drvdata(pdev, dsi);709 dsi->dev = &pdev->dev;710 711 ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4);712 if (ret < 0)713 return dev_err_probe(dsi->dev, ret,714 "missing or invalid data-lanes property\n");715 716 num_data_lanes = ret;717 718 dsi->mmio = devm_platform_ioremap_resource(pdev, 0);719 if (IS_ERR(dsi->mmio))720 return PTR_ERR(dsi->mmio);721 722 dsi->vclk = devm_clk_get(dsi->dev, "vclk");723 if (IS_ERR(dsi->vclk))724 return PTR_ERR(dsi->vclk);725 726 dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst");727 if (IS_ERR(dsi->rstc))728 return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc),729 "failed to get rst\n");730 731 dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst");732 if (IS_ERR(dsi->arstc))733 return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc),734 "failed to get arst\n");735 736 dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst");737 if (IS_ERR(dsi->prstc))738 return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc),739 "failed to get prst\n");740 741 platform_set_drvdata(pdev, dsi);742 743 pm_runtime_enable(dsi->dev);744 745 ret = pm_runtime_resume_and_get(dsi->dev);746 if (ret < 0)747 goto err_pm_disable;748 749 /*750 * TXSETR register can be read only after DPHY init. But during probe751 * mode->clock and format are not available. So initialize DPHY with752 * timing parameters for 80Mbps.753 */754 ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000);755 if (ret < 0)756 goto err_phy;757 758 txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR);759 dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes);760 rzg2l_mipi_dsi_dphy_exit(dsi);761 pm_runtime_put(dsi->dev);762 763 /* Initialize the DRM bridge. */764 dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops;765 dsi->bridge.of_node = dsi->dev->of_node;766 767 /* Init host device */768 dsi->host.dev = dsi->dev;769 dsi->host.ops = &rzg2l_mipi_dsi_host_ops;770 ret = mipi_dsi_host_register(&dsi->host);771 if (ret < 0)772 goto err_pm_disable;773 774 return 0;775 776err_phy:777 rzg2l_mipi_dsi_dphy_exit(dsi);778 pm_runtime_put(dsi->dev);779err_pm_disable:780 pm_runtime_disable(dsi->dev);781 return ret;782}783 784static void rzg2l_mipi_dsi_remove(struct platform_device *pdev)785{786 struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);787 788 mipi_dsi_host_unregister(&dsi->host);789 pm_runtime_disable(&pdev->dev);790}791 792static const struct of_device_id rzg2l_mipi_dsi_of_table[] = {793 { .compatible = "renesas,rzg2l-mipi-dsi" },794 { /* sentinel */ }795};796 797MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table);798 799static struct platform_driver rzg2l_mipi_dsi_platform_driver = {800 .probe = rzg2l_mipi_dsi_probe,801 .remove_new = rzg2l_mipi_dsi_remove,802 .driver = {803 .name = "rzg2l-mipi-dsi",804 .pm = &rzg2l_mipi_pm_ops,805 .of_match_table = rzg2l_mipi_dsi_of_table,806 },807};808 809module_platform_driver(rzg2l_mipi_dsi_platform_driver);810 811MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");812MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver");813MODULE_LICENSE("GPL");814