linux/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
   4 */
   5
   6#include <linux/clk-provider.h>
   7#include <linux/platform_device.h>
   8#include <dt-bindings/phy/phy.h>
   9
  10#include "dsi_phy.h"
  11
  12#define S_DIV_ROUND_UP(n, d)    \
  13        (((n) >= 0) ? (((n) + (d) - 1) / (d)) : (((n) - (d) + 1) / (d)))
  14
  15static inline s32 linear_inter(s32 tmax, s32 tmin, s32 percent,
  16                                s32 min_result, bool even)
  17{
  18        s32 v;
  19
  20        v = (tmax - tmin) * percent;
  21        v = S_DIV_ROUND_UP(v, 100) + tmin;
  22        if (even && (v & 0x1))
  23                return max_t(s32, min_result, v - 1);
  24        else
  25                return max_t(s32, min_result, v);
  26}
  27
  28static void dsi_dphy_timing_calc_clk_zero(struct msm_dsi_dphy_timing *timing,
  29                                        s32 ui, s32 coeff, s32 pcnt)
  30{
  31        s32 tmax, tmin, clk_z;
  32        s32 temp;
  33
  34        /* reset */
  35        temp = 300 * coeff - ((timing->clk_prepare >> 1) + 1) * 2 * ui;
  36        tmin = S_DIV_ROUND_UP(temp, ui) - 2;
  37        if (tmin > 255) {
  38                tmax = 511;
  39                clk_z = linear_inter(2 * tmin, tmin, pcnt, 0, true);
  40        } else {
  41                tmax = 255;
  42                clk_z = linear_inter(tmax, tmin, pcnt, 0, true);
  43        }
  44
  45        /* adjust */
  46        temp = (timing->hs_rqst + timing->clk_prepare + clk_z) & 0x7;
  47        timing->clk_zero = clk_z + 8 - temp;
  48}
  49
  50int msm_dsi_dphy_timing_calc(struct msm_dsi_dphy_timing *timing,
  51                             struct msm_dsi_phy_clk_request *clk_req)
  52{
  53        const unsigned long bit_rate = clk_req->bitclk_rate;
  54        const unsigned long esc_rate = clk_req->escclk_rate;
  55        s32 ui, lpx;
  56        s32 tmax, tmin;
  57        s32 pcnt0 = 10;
  58        s32 pcnt1 = (bit_rate > 1200000000) ? 15 : 10;
  59        s32 pcnt2 = 10;
  60        s32 pcnt3 = (bit_rate > 180000000) ? 10 : 40;
  61        s32 coeff = 1000; /* Precision, should avoid overflow */
  62        s32 temp;
  63
  64        if (!bit_rate || !esc_rate)
  65                return -EINVAL;
  66
  67        ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000);
  68        lpx = mult_frac(NSEC_PER_MSEC, coeff, esc_rate / 1000);
  69
  70        tmax = S_DIV_ROUND_UP(95 * coeff, ui) - 2;
  71        tmin = S_DIV_ROUND_UP(38 * coeff, ui) - 2;
  72        timing->clk_prepare = linear_inter(tmax, tmin, pcnt0, 0, true);
  73
  74        temp = lpx / ui;
  75        if (temp & 0x1)
  76                timing->hs_rqst = temp;
  77        else
  78                timing->hs_rqst = max_t(s32, 0, temp - 2);
  79
  80        /* Calculate clk_zero after clk_prepare and hs_rqst */
  81        dsi_dphy_timing_calc_clk_zero(timing, ui, coeff, pcnt2);
  82
  83        temp = 105 * coeff + 12 * ui - 20 * coeff;
  84        tmax = S_DIV_ROUND_UP(temp, ui) - 2;
  85        tmin = S_DIV_ROUND_UP(60 * coeff, ui) - 2;
  86        timing->clk_trail = linear_inter(tmax, tmin, pcnt3, 0, true);
  87
  88        temp = 85 * coeff + 6 * ui;
  89        tmax = S_DIV_ROUND_UP(temp, ui) - 2;
  90        temp = 40 * coeff + 4 * ui;
  91        tmin = S_DIV_ROUND_UP(temp, ui) - 2;
  92        timing->hs_prepare = linear_inter(tmax, tmin, pcnt1, 0, true);
  93
  94        tmax = 255;
  95        temp = ((timing->hs_prepare >> 1) + 1) * 2 * ui + 2 * ui;
  96        temp = 145 * coeff + 10 * ui - temp;
  97        tmin = S_DIV_ROUND_UP(temp, ui) - 2;
  98        timing->hs_zero = linear_inter(tmax, tmin, pcnt2, 24, true);
  99
 100        temp = 105 * coeff + 12 * ui - 20 * coeff;
 101        tmax = S_DIV_ROUND_UP(temp, ui) - 2;
 102        temp = 60 * coeff + 4 * ui;
 103        tmin = DIV_ROUND_UP(temp, ui) - 2;
 104        timing->hs_trail = linear_inter(tmax, tmin, pcnt3, 0, true);
 105
 106        tmax = 255;
 107        tmin = S_DIV_ROUND_UP(100 * coeff, ui) - 2;
 108        timing->hs_exit = linear_inter(tmax, tmin, pcnt2, 0, true);
 109
 110        tmax = 63;
 111        temp = ((timing->hs_exit >> 1) + 1) * 2 * ui;
 112        temp = 60 * coeff + 52 * ui - 24 * ui - temp;
 113        tmin = S_DIV_ROUND_UP(temp, 8 * ui) - 1;
 114        timing->shared_timings.clk_post = linear_inter(tmax, tmin, pcnt2, 0,
 115                                                       false);
 116        tmax = 63;
 117        temp = ((timing->clk_prepare >> 1) + 1) * 2 * ui;
 118        temp += ((timing->clk_zero >> 1) + 1) * 2 * ui;
 119        temp += 8 * ui + lpx;
 120        tmin = S_DIV_ROUND_UP(temp, 8 * ui) - 1;
 121        if (tmin > tmax) {
 122                temp = linear_inter(2 * tmax, tmin, pcnt2, 0, false);
 123                timing->shared_timings.clk_pre = temp >> 1;
 124                timing->shared_timings.clk_pre_inc_by_2 = true;
 125        } else {
 126                timing->shared_timings.clk_pre =
 127                                linear_inter(tmax, tmin, pcnt2, 0, false);
 128                timing->shared_timings.clk_pre_inc_by_2 = false;
 129        }
 130
 131        timing->ta_go = 3;
 132        timing->ta_sure = 0;
 133        timing->ta_get = 4;
 134
 135        DBG("PHY timings: %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
 136                timing->shared_timings.clk_pre, timing->shared_timings.clk_post,
 137                timing->shared_timings.clk_pre_inc_by_2, timing->clk_zero,
 138                timing->clk_trail, timing->clk_prepare, timing->hs_exit,
 139                timing->hs_zero, timing->hs_prepare, timing->hs_trail,
 140                timing->hs_rqst);
 141
 142        return 0;
 143}
 144
 145int msm_dsi_dphy_timing_calc_v2(struct msm_dsi_dphy_timing *timing,
 146                                struct msm_dsi_phy_clk_request *clk_req)
 147{
 148        const unsigned long bit_rate = clk_req->bitclk_rate;
 149        const unsigned long esc_rate = clk_req->escclk_rate;
 150        s32 ui, ui_x8;
 151        s32 tmax, tmin;
 152        s32 pcnt0 = 50;
 153        s32 pcnt1 = 50;
 154        s32 pcnt2 = 10;
 155        s32 pcnt3 = 30;
 156        s32 pcnt4 = 10;
 157        s32 pcnt5 = 2;
 158        s32 coeff = 1000; /* Precision, should avoid overflow */
 159        s32 hb_en, hb_en_ckln, pd_ckln, pd;
 160        s32 val, val_ckln;
 161        s32 temp;
 162
 163        if (!bit_rate || !esc_rate)
 164                return -EINVAL;
 165
 166        timing->hs_halfbyte_en = 0;
 167        hb_en = 0;
 168        timing->hs_halfbyte_en_ckln = 0;
 169        hb_en_ckln = 0;
 170        timing->hs_prep_dly_ckln = (bit_rate > 100000000) ? 0 : 3;
 171        pd_ckln = timing->hs_prep_dly_ckln;
 172        timing->hs_prep_dly = (bit_rate > 120000000) ? 0 : 1;
 173        pd = timing->hs_prep_dly;
 174
 175        val = (hb_en << 2) + (pd << 1);
 176        val_ckln = (hb_en_ckln << 2) + (pd_ckln << 1);
 177
 178        ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000);
 179        ui_x8 = ui << 3;
 180
 181        temp = S_DIV_ROUND_UP(38 * coeff - val_ckln * ui, ui_x8);
 182        tmin = max_t(s32, temp, 0);
 183        temp = (95 * coeff - val_ckln * ui) / ui_x8;
 184        tmax = max_t(s32, temp, 0);
 185        timing->clk_prepare = linear_inter(tmax, tmin, pcnt0, 0, false);
 186
 187        temp = 300 * coeff - ((timing->clk_prepare << 3) + val_ckln) * ui;
 188        tmin = S_DIV_ROUND_UP(temp - 11 * ui, ui_x8) - 3;
 189        tmax = (tmin > 255) ? 511 : 255;
 190        timing->clk_zero = linear_inter(tmax, tmin, pcnt5, 0, false);
 191
 192        tmin = DIV_ROUND_UP(60 * coeff + 3 * ui, ui_x8);
 193        temp = 105 * coeff + 12 * ui - 20 * coeff;
 194        tmax = (temp + 3 * ui) / ui_x8;
 195        timing->clk_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
 196
 197        temp = S_DIV_ROUND_UP(40 * coeff + 4 * ui - val * ui, ui_x8);
 198        tmin = max_t(s32, temp, 0);
 199        temp = (85 * coeff + 6 * ui - val * ui) / ui_x8;
 200        tmax = max_t(s32, temp, 0);
 201        timing->hs_prepare = linear_inter(tmax, tmin, pcnt1, 0, false);
 202
 203        temp = 145 * coeff + 10 * ui - ((timing->hs_prepare << 3) + val) * ui;
 204        tmin = S_DIV_ROUND_UP(temp - 11 * ui, ui_x8) - 3;
 205        tmax = 255;
 206        timing->hs_zero = linear_inter(tmax, tmin, pcnt4, 0, false);
 207
 208        tmin = DIV_ROUND_UP(60 * coeff + 4 * ui + 3 * ui, ui_x8);
 209        temp = 105 * coeff + 12 * ui - 20 * coeff;
 210        tmax = (temp + 3 * ui) / ui_x8;
 211        timing->hs_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
 212
 213        temp = 50 * coeff + ((hb_en << 2) - 8) * ui;
 214        timing->hs_rqst = S_DIV_ROUND_UP(temp, ui_x8);
 215
 216        tmin = DIV_ROUND_UP(100 * coeff, ui_x8) - 1;
 217        tmax = 255;
 218        timing->hs_exit = linear_inter(tmax, tmin, pcnt2, 0, false);
 219
 220        temp = 50 * coeff + ((hb_en_ckln << 2) - 8) * ui;
 221        timing->hs_rqst_ckln = S_DIV_ROUND_UP(temp, ui_x8);
 222
 223        temp = 60 * coeff + 52 * ui - 43 * ui;
 224        tmin = DIV_ROUND_UP(temp, ui_x8) - 1;
 225        tmax = 63;
 226        timing->shared_timings.clk_post =
 227                                linear_inter(tmax, tmin, pcnt2, 0, false);
 228
 229        temp = 8 * ui + ((timing->clk_prepare << 3) + val_ckln) * ui;
 230        temp += (((timing->clk_zero + 3) << 3) + 11 - (pd_ckln << 1)) * ui;
 231        temp += hb_en_ckln ? (((timing->hs_rqst_ckln << 3) + 4) * ui) :
 232                                (((timing->hs_rqst_ckln << 3) + 8) * ui);
 233        tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
 234        tmax = 63;
 235        if (tmin > tmax) {
 236                temp = linear_inter(tmax << 1, tmin, pcnt2, 0, false);
 237                timing->shared_timings.clk_pre = temp >> 1;
 238                timing->shared_timings.clk_pre_inc_by_2 = 1;
 239        } else {
 240                timing->shared_timings.clk_pre =
 241                                linear_inter(tmax, tmin, pcnt2, 0, false);
 242                timing->shared_timings.clk_pre_inc_by_2 = 0;
 243        }
 244
 245        timing->ta_go = 3;
 246        timing->ta_sure = 0;
 247        timing->ta_get = 4;
 248
 249        DBG("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
 250            timing->shared_timings.clk_pre, timing->shared_timings.clk_post,
 251            timing->shared_timings.clk_pre_inc_by_2, timing->clk_zero,
 252            timing->clk_trail, timing->clk_prepare, timing->hs_exit,
 253            timing->hs_zero, timing->hs_prepare, timing->hs_trail,
 254            timing->hs_rqst, timing->hs_rqst_ckln, timing->hs_halfbyte_en,
 255            timing->hs_halfbyte_en_ckln, timing->hs_prep_dly,
 256            timing->hs_prep_dly_ckln);
 257
 258        return 0;
 259}
 260
 261int msm_dsi_dphy_timing_calc_v3(struct msm_dsi_dphy_timing *timing,
 262        struct msm_dsi_phy_clk_request *clk_req)
 263{
 264        const unsigned long bit_rate = clk_req->bitclk_rate;
 265        const unsigned long esc_rate = clk_req->escclk_rate;
 266        s32 ui, ui_x8;
 267        s32 tmax, tmin;
 268        s32 pcnt0 = 50;
 269        s32 pcnt1 = 50;
 270        s32 pcnt2 = 10;
 271        s32 pcnt3 = 30;
 272        s32 pcnt4 = 10;
 273        s32 pcnt5 = 2;
 274        s32 coeff = 1000; /* Precision, should avoid overflow */
 275        s32 hb_en, hb_en_ckln;
 276        s32 temp;
 277
 278        if (!bit_rate || !esc_rate)
 279                return -EINVAL;
 280
 281        timing->hs_halfbyte_en = 0;
 282        hb_en = 0;
 283        timing->hs_halfbyte_en_ckln = 0;
 284        hb_en_ckln = 0;
 285
 286        ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000);
 287        ui_x8 = ui << 3;
 288
 289        temp = S_DIV_ROUND_UP(38 * coeff, ui_x8);
 290        tmin = max_t(s32, temp, 0);
 291        temp = (95 * coeff) / ui_x8;
 292        tmax = max_t(s32, temp, 0);
 293        timing->clk_prepare = linear_inter(tmax, tmin, pcnt0, 0, false);
 294
 295        temp = 300 * coeff - (timing->clk_prepare << 3) * ui;
 296        tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
 297        tmax = (tmin > 255) ? 511 : 255;
 298        timing->clk_zero = linear_inter(tmax, tmin, pcnt5, 0, false);
 299
 300        tmin = DIV_ROUND_UP(60 * coeff + 3 * ui, ui_x8);
 301        temp = 105 * coeff + 12 * ui - 20 * coeff;
 302        tmax = (temp + 3 * ui) / ui_x8;
 303        timing->clk_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
 304
 305        temp = S_DIV_ROUND_UP(40 * coeff + 4 * ui, ui_x8);
 306        tmin = max_t(s32, temp, 0);
 307        temp = (85 * coeff + 6 * ui) / ui_x8;
 308        tmax = max_t(s32, temp, 0);
 309        timing->hs_prepare = linear_inter(tmax, tmin, pcnt1, 0, false);
 310
 311        temp = 145 * coeff + 10 * ui - (timing->hs_prepare << 3) * ui;
 312        tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
 313        tmax = 255;
 314        timing->hs_zero = linear_inter(tmax, tmin, pcnt4, 0, false);
 315
 316        tmin = DIV_ROUND_UP(60 * coeff + 4 * ui, ui_x8) - 1;
 317        temp = 105 * coeff + 12 * ui - 20 * coeff;
 318        tmax = (temp / ui_x8) - 1;
 319        timing->hs_trail = linear_inter(tmax, tmin, pcnt3, 0, false);
 320
 321        temp = 50 * coeff + ((hb_en << 2) - 8) * ui;
 322        timing->hs_rqst = S_DIV_ROUND_UP(temp, ui_x8);
 323
 324        tmin = DIV_ROUND_UP(100 * coeff, ui_x8) - 1;
 325        tmax = 255;
 326        timing->hs_exit = linear_inter(tmax, tmin, pcnt2, 0, false);
 327
 328        temp = 50 * coeff + ((hb_en_ckln << 2) - 8) * ui;
 329        timing->hs_rqst_ckln = S_DIV_ROUND_UP(temp, ui_x8);
 330
 331        temp = 60 * coeff + 52 * ui - 43 * ui;
 332        tmin = DIV_ROUND_UP(temp, ui_x8) - 1;
 333        tmax = 63;
 334        timing->shared_timings.clk_post =
 335                linear_inter(tmax, tmin, pcnt2, 0, false);
 336
 337        temp = 8 * ui + (timing->clk_prepare << 3) * ui;
 338        temp += (((timing->clk_zero + 3) << 3) + 11) * ui;
 339        temp += hb_en_ckln ? (((timing->hs_rqst_ckln << 3) + 4) * ui) :
 340                (((timing->hs_rqst_ckln << 3) + 8) * ui);
 341        tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
 342        tmax = 63;
 343        if (tmin > tmax) {
 344                temp = linear_inter(tmax << 1, tmin, pcnt2, 0, false);
 345                timing->shared_timings.clk_pre = temp >> 1;
 346                timing->shared_timings.clk_pre_inc_by_2 = 1;
 347        } else {
 348                timing->shared_timings.clk_pre =
 349                        linear_inter(tmax, tmin, pcnt2, 0, false);
 350                        timing->shared_timings.clk_pre_inc_by_2 = 0;
 351        }
 352
 353        timing->ta_go = 3;
 354        timing->ta_sure = 0;
 355        timing->ta_get = 4;
 356
 357        DBG("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
 358                timing->shared_timings.clk_pre, timing->shared_timings.clk_post,
 359                timing->shared_timings.clk_pre_inc_by_2, timing->clk_zero,
 360                timing->clk_trail, timing->clk_prepare, timing->hs_exit,
 361                timing->hs_zero, timing->hs_prepare, timing->hs_trail,
 362                timing->hs_rqst, timing->hs_rqst_ckln, timing->hs_halfbyte_en,
 363                timing->hs_halfbyte_en_ckln, timing->hs_prep_dly,
 364                timing->hs_prep_dly_ckln);
 365
 366        return 0;
 367}
 368
 369int msm_dsi_dphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing,
 370        struct msm_dsi_phy_clk_request *clk_req)
 371{
 372        const unsigned long bit_rate = clk_req->bitclk_rate;
 373        const unsigned long esc_rate = clk_req->escclk_rate;
 374        s32 ui, ui_x8;
 375        s32 tmax, tmin;
 376        s32 pcnt_clk_prep = 50;
 377        s32 pcnt_clk_zero = 2;
 378        s32 pcnt_clk_trail = 30;
 379        s32 pcnt_hs_prep = 50;
 380        s32 pcnt_hs_zero = 10;
 381        s32 pcnt_hs_trail = 30;
 382        s32 pcnt_hs_exit = 10;
 383        s32 coeff = 1000; /* Precision, should avoid overflow */
 384        s32 hb_en;
 385        s32 temp;
 386
 387        if (!bit_rate || !esc_rate)
 388                return -EINVAL;
 389
 390        hb_en = 0;
 391
 392        ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000);
 393        ui_x8 = ui << 3;
 394
 395        /* TODO: verify these calculations against latest downstream driver
 396         * everything except clk_post/clk_pre uses calculations from v3 based
 397         * on the downstream driver having the same calculations for v3 and v4
 398         */
 399
 400        temp = S_DIV_ROUND_UP(38 * coeff, ui_x8);
 401        tmin = max_t(s32, temp, 0);
 402        temp = (95 * coeff) / ui_x8;
 403        tmax = max_t(s32, temp, 0);
 404        timing->clk_prepare = linear_inter(tmax, tmin, pcnt_clk_prep, 0, false);
 405
 406        temp = 300 * coeff - (timing->clk_prepare << 3) * ui;
 407        tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
 408        tmax = (tmin > 255) ? 511 : 255;
 409        timing->clk_zero = linear_inter(tmax, tmin, pcnt_clk_zero, 0, false);
 410
 411        tmin = DIV_ROUND_UP(60 * coeff + 3 * ui, ui_x8);
 412        temp = 105 * coeff + 12 * ui - 20 * coeff;
 413        tmax = (temp + 3 * ui) / ui_x8;
 414        timing->clk_trail = linear_inter(tmax, tmin, pcnt_clk_trail, 0, false);
 415
 416        temp = S_DIV_ROUND_UP(40 * coeff + 4 * ui, ui_x8);
 417        tmin = max_t(s32, temp, 0);
 418        temp = (85 * coeff + 6 * ui) / ui_x8;
 419        tmax = max_t(s32, temp, 0);
 420        timing->hs_prepare = linear_inter(tmax, tmin, pcnt_hs_prep, 0, false);
 421
 422        temp = 145 * coeff + 10 * ui - (timing->hs_prepare << 3) * ui;
 423        tmin = S_DIV_ROUND_UP(temp, ui_x8) - 1;
 424        tmax = 255;
 425        timing->hs_zero = linear_inter(tmax, tmin, pcnt_hs_zero, 0, false);
 426
 427        tmin = DIV_ROUND_UP(60 * coeff + 4 * ui, ui_x8) - 1;
 428        temp = 105 * coeff + 12 * ui - 20 * coeff;
 429        tmax = (temp / ui_x8) - 1;
 430        timing->hs_trail = linear_inter(tmax, tmin, pcnt_hs_trail, 0, false);
 431
 432        temp = 50 * coeff + ((hb_en << 2) - 8) * ui;
 433        timing->hs_rqst = S_DIV_ROUND_UP(temp, ui_x8);
 434
 435        tmin = DIV_ROUND_UP(100 * coeff, ui_x8) - 1;
 436        tmax = 255;
 437        timing->hs_exit = linear_inter(tmax, tmin, pcnt_hs_exit, 0, false);
 438
 439        /* recommended min
 440         * = roundup((mipi_min_ns + t_hs_trail_ns)/(16*bit_clk_ns), 0) - 1
 441         */
 442        temp = 60 * coeff + 52 * ui + + (timing->hs_trail + 1) * ui_x8;
 443        tmin = DIV_ROUND_UP(temp, 16 * ui) - 1;
 444        tmax = 255;
 445        timing->shared_timings.clk_post = linear_inter(tmax, tmin, 5, 0, false);
 446
 447        /* recommended min
 448         * val1 = (tlpx_ns + clk_prepare_ns + clk_zero_ns + hs_rqst_ns)
 449         * val2 = (16 * bit_clk_ns)
 450         * final = roundup(val1/val2, 0) - 1
 451         */
 452        temp = 52 * coeff + (timing->clk_prepare + timing->clk_zero + 1) * ui_x8 + 54 * coeff;
 453        tmin = DIV_ROUND_UP(temp, 16 * ui) - 1;
 454        tmax = 255;
 455        timing->shared_timings.clk_pre = DIV_ROUND_UP((tmax - tmin) * 125, 10000) + tmin;
 456
 457        DBG("%d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
 458                timing->shared_timings.clk_pre, timing->shared_timings.clk_post,
 459                timing->clk_zero, timing->clk_trail, timing->clk_prepare, timing->hs_exit,
 460                timing->hs_zero, timing->hs_prepare, timing->hs_trail, timing->hs_rqst);
 461
 462        return 0;
 463}
 464
 465int msm_dsi_cphy_timing_calc_v4(struct msm_dsi_dphy_timing *timing,
 466        struct msm_dsi_phy_clk_request *clk_req)
 467{
 468        const unsigned long bit_rate = clk_req->bitclk_rate;
 469        const unsigned long esc_rate = clk_req->escclk_rate;
 470        s32 ui, ui_x7;
 471        s32 tmax, tmin;
 472        s32 coeff = 1000; /* Precision, should avoid overflow */
 473        s32 temp;
 474
 475        if (!bit_rate || !esc_rate)
 476                return -EINVAL;
 477
 478        ui = mult_frac(NSEC_PER_MSEC, coeff, bit_rate / 1000);
 479        ui_x7 = ui * 7;
 480
 481        temp = S_DIV_ROUND_UP(38 * coeff, ui_x7);
 482        tmin = max_t(s32, temp, 0);
 483        temp = (95 * coeff) / ui_x7;
 484        tmax = max_t(s32, temp, 0);
 485        timing->clk_prepare = linear_inter(tmax, tmin, 50, 0, false);
 486
 487        tmin = DIV_ROUND_UP(50 * coeff, ui_x7);
 488        tmax = 255;
 489        timing->hs_rqst = linear_inter(tmax, tmin, 1, 0, false);
 490
 491        tmin = DIV_ROUND_UP(100 * coeff, ui_x7) - 1;
 492        tmax = 255;
 493        timing->hs_exit = linear_inter(tmax, tmin, 10, 0, false);
 494
 495        tmin = 1;
 496        tmax = 32;
 497        timing->shared_timings.clk_post = linear_inter(tmax, tmin, 80, 0, false);
 498
 499        tmin = min_t(s32, 64, S_DIV_ROUND_UP(262 * coeff, ui_x7) - 1);
 500        tmax = 64;
 501        timing->shared_timings.clk_pre = linear_inter(tmax, tmin, 20, 0, false);
 502
 503        DBG("%d, %d, %d, %d, %d",
 504                timing->shared_timings.clk_pre, timing->shared_timings.clk_post,
 505                timing->clk_prepare, timing->hs_exit, timing->hs_rqst);
 506
 507        return 0;
 508}
 509
 510static int dsi_phy_regulator_init(struct msm_dsi_phy *phy)
 511{
 512        struct regulator_bulk_data *s = phy->supplies;
 513        const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
 514        struct device *dev = &phy->pdev->dev;
 515        int num = phy->cfg->reg_cfg.num;
 516        int i, ret;
 517
 518        for (i = 0; i < num; i++)
 519                s[i].supply = regs[i].name;
 520
 521        ret = devm_regulator_bulk_get(dev, num, s);
 522        if (ret < 0) {
 523                if (ret != -EPROBE_DEFER) {
 524                        DRM_DEV_ERROR(dev,
 525                                      "%s: failed to init regulator, ret=%d\n",
 526                                      __func__, ret);
 527                }
 528
 529                return ret;
 530        }
 531
 532        return 0;
 533}
 534
 535static void dsi_phy_regulator_disable(struct msm_dsi_phy *phy)
 536{
 537        struct regulator_bulk_data *s = phy->supplies;
 538        const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
 539        int num = phy->cfg->reg_cfg.num;
 540        int i;
 541
 542        DBG("");
 543        for (i = num - 1; i >= 0; i--)
 544                if (regs[i].disable_load >= 0)
 545                        regulator_set_load(s[i].consumer, regs[i].disable_load);
 546
 547        regulator_bulk_disable(num, s);
 548}
 549
 550static int dsi_phy_regulator_enable(struct msm_dsi_phy *phy)
 551{
 552        struct regulator_bulk_data *s = phy->supplies;
 553        const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
 554        struct device *dev = &phy->pdev->dev;
 555        int num = phy->cfg->reg_cfg.num;
 556        int ret, i;
 557
 558        DBG("");
 559        for (i = 0; i < num; i++) {
 560                if (regs[i].enable_load >= 0) {
 561                        ret = regulator_set_load(s[i].consumer,
 562                                                        regs[i].enable_load);
 563                        if (ret < 0) {
 564                                DRM_DEV_ERROR(dev,
 565                                        "regulator %d set op mode failed, %d\n",
 566                                        i, ret);
 567                                goto fail;
 568                        }
 569                }
 570        }
 571
 572        ret = regulator_bulk_enable(num, s);
 573        if (ret < 0) {
 574                DRM_DEV_ERROR(dev, "regulator enable failed, %d\n", ret);
 575                goto fail;
 576        }
 577
 578        return 0;
 579
 580fail:
 581        for (i--; i >= 0; i--)
 582                regulator_set_load(s[i].consumer, regs[i].disable_load);
 583        return ret;
 584}
 585
 586static int dsi_phy_enable_resource(struct msm_dsi_phy *phy)
 587{
 588        struct device *dev = &phy->pdev->dev;
 589        int ret;
 590
 591        pm_runtime_get_sync(dev);
 592
 593        ret = clk_prepare_enable(phy->ahb_clk);
 594        if (ret) {
 595                DRM_DEV_ERROR(dev, "%s: can't enable ahb clk, %d\n", __func__, ret);
 596                pm_runtime_put_sync(dev);
 597        }
 598
 599        return ret;
 600}
 601
 602static void dsi_phy_disable_resource(struct msm_dsi_phy *phy)
 603{
 604        clk_disable_unprepare(phy->ahb_clk);
 605        pm_runtime_put_autosuspend(&phy->pdev->dev);
 606}
 607
 608static const struct of_device_id dsi_phy_dt_match[] = {
 609#ifdef CONFIG_DRM_MSM_DSI_28NM_PHY
 610        { .compatible = "qcom,dsi-phy-28nm-hpm",
 611          .data = &dsi_phy_28nm_hpm_cfgs },
 612        { .compatible = "qcom,dsi-phy-28nm-hpm-fam-b",
 613          .data = &dsi_phy_28nm_hpm_famb_cfgs },
 614        { .compatible = "qcom,dsi-phy-28nm-lp",
 615          .data = &dsi_phy_28nm_lp_cfgs },
 616#endif
 617#ifdef CONFIG_DRM_MSM_DSI_20NM_PHY
 618        { .compatible = "qcom,dsi-phy-20nm",
 619          .data = &dsi_phy_20nm_cfgs },
 620#endif
 621#ifdef CONFIG_DRM_MSM_DSI_28NM_8960_PHY
 622        { .compatible = "qcom,dsi-phy-28nm-8960",
 623          .data = &dsi_phy_28nm_8960_cfgs },
 624#endif
 625#ifdef CONFIG_DRM_MSM_DSI_14NM_PHY
 626        { .compatible = "qcom,dsi-phy-14nm",
 627          .data = &dsi_phy_14nm_cfgs },
 628        { .compatible = "qcom,dsi-phy-14nm-660",
 629          .data = &dsi_phy_14nm_660_cfgs },
 630#endif
 631#ifdef CONFIG_DRM_MSM_DSI_10NM_PHY
 632        { .compatible = "qcom,dsi-phy-10nm",
 633          .data = &dsi_phy_10nm_cfgs },
 634        { .compatible = "qcom,dsi-phy-10nm-8998",
 635          .data = &dsi_phy_10nm_8998_cfgs },
 636#endif
 637#ifdef CONFIG_DRM_MSM_DSI_7NM_PHY
 638        { .compatible = "qcom,dsi-phy-7nm",
 639          .data = &dsi_phy_7nm_cfgs },
 640        { .compatible = "qcom,dsi-phy-7nm-8150",
 641          .data = &dsi_phy_7nm_8150_cfgs },
 642        { .compatible = "qcom,sc7280-dsi-phy-7nm",
 643          .data = &dsi_phy_7nm_7280_cfgs },
 644#endif
 645        {}
 646};
 647
 648/*
 649 * Currently, we only support one SoC for each PHY type. When we have multiple
 650 * SoCs for the same PHY, we can try to make the index searching a bit more
 651 * clever.
 652 */
 653static int dsi_phy_get_id(struct msm_dsi_phy *phy)
 654{
 655        struct platform_device *pdev = phy->pdev;
 656        const struct msm_dsi_phy_cfg *cfg = phy->cfg;
 657        struct resource *res;
 658        int i;
 659
 660        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dsi_phy");
 661        if (!res)
 662                return -EINVAL;
 663
 664        for (i = 0; i < cfg->num_dsi_phy; i++) {
 665                if (cfg->io_start[i] == res->start)
 666                        return i;
 667        }
 668
 669        return -EINVAL;
 670}
 671
 672static int dsi_phy_driver_probe(struct platform_device *pdev)
 673{
 674        struct msm_dsi_phy *phy;
 675        struct device *dev = &pdev->dev;
 676        u32 phy_type;
 677        int ret;
 678
 679        phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
 680        if (!phy)
 681                return -ENOMEM;
 682
 683        phy->provided_clocks = devm_kzalloc(dev,
 684                        struct_size(phy->provided_clocks, hws, NUM_PROVIDED_CLKS),
 685                        GFP_KERNEL);
 686        if (!phy->provided_clocks)
 687                return -ENOMEM;
 688
 689        phy->provided_clocks->num = NUM_PROVIDED_CLKS;
 690
 691        phy->cfg = of_device_get_match_data(&pdev->dev);
 692        if (!phy->cfg)
 693                return -ENODEV;
 694
 695        phy->pdev = pdev;
 696
 697        phy->id = dsi_phy_get_id(phy);
 698        if (phy->id < 0) {
 699                ret = phy->id;
 700                DRM_DEV_ERROR(dev, "%s: couldn't identify PHY index, %d\n",
 701                        __func__, ret);
 702                goto fail;
 703        }
 704
 705        phy->regulator_ldo_mode = of_property_read_bool(dev->of_node,
 706                                "qcom,dsi-phy-regulator-ldo-mode");
 707        if (!of_property_read_u32(dev->of_node, "phy-type", &phy_type))
 708                phy->cphy_mode = (phy_type == PHY_TYPE_CPHY);
 709
 710        phy->base = msm_ioremap_size(pdev, "dsi_phy", "DSI_PHY", &phy->base_size);
 711        if (IS_ERR(phy->base)) {
 712                DRM_DEV_ERROR(dev, "%s: failed to map phy base\n", __func__);
 713                ret = -ENOMEM;
 714                goto fail;
 715        }
 716
 717        phy->pll_base = msm_ioremap_size(pdev, "dsi_pll", "DSI_PLL", &phy->pll_size);
 718        if (IS_ERR(phy->pll_base)) {
 719                DRM_DEV_ERROR(&pdev->dev, "%s: failed to map pll base\n", __func__);
 720                ret = -ENOMEM;
 721                goto fail;
 722        }
 723
 724        if (phy->cfg->has_phy_lane) {
 725                phy->lane_base = msm_ioremap_size(pdev, "dsi_phy_lane", "DSI_PHY_LANE", &phy->lane_size);
 726                if (IS_ERR(phy->lane_base)) {
 727                        DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy lane base\n", __func__);
 728                        ret = -ENOMEM;
 729                        goto fail;
 730                }
 731        }
 732
 733        if (phy->cfg->has_phy_regulator) {
 734                phy->reg_base = msm_ioremap_size(pdev, "dsi_phy_regulator", "DSI_PHY_REG", &phy->reg_size);
 735                if (IS_ERR(phy->reg_base)) {
 736                        DRM_DEV_ERROR(&pdev->dev, "%s: failed to map phy regulator base\n", __func__);
 737                        ret = -ENOMEM;
 738                        goto fail;
 739                }
 740        }
 741
 742        ret = dsi_phy_regulator_init(phy);
 743        if (ret)
 744                goto fail;
 745
 746        phy->ahb_clk = msm_clk_get(pdev, "iface");
 747        if (IS_ERR(phy->ahb_clk)) {
 748                DRM_DEV_ERROR(dev, "%s: Unable to get ahb clk\n", __func__);
 749                ret = PTR_ERR(phy->ahb_clk);
 750                goto fail;
 751        }
 752
 753        /* PLL init will call into clk_register which requires
 754         * register access, so we need to enable power and ahb clock.
 755         */
 756        ret = dsi_phy_enable_resource(phy);
 757        if (ret)
 758                goto fail;
 759
 760        if (phy->cfg->ops.pll_init) {
 761                ret = phy->cfg->ops.pll_init(phy);
 762                if (ret) {
 763                        DRM_DEV_INFO(dev,
 764                                "%s: pll init failed: %d, need separate pll clk driver\n",
 765                                __func__, ret);
 766                        goto fail;
 767                }
 768        }
 769
 770        ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
 771                                     phy->provided_clocks);
 772        if (ret) {
 773                DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__, ret);
 774                goto fail;
 775        }
 776
 777        dsi_phy_disable_resource(phy);
 778
 779        platform_set_drvdata(pdev, phy);
 780
 781        return 0;
 782
 783fail:
 784        return ret;
 785}
 786
 787static struct platform_driver dsi_phy_platform_driver = {
 788        .probe      = dsi_phy_driver_probe,
 789        .driver     = {
 790                .name   = "msm_dsi_phy",
 791                .of_match_table = dsi_phy_dt_match,
 792        },
 793};
 794
 795void __init msm_dsi_phy_driver_register(void)
 796{
 797        platform_driver_register(&dsi_phy_platform_driver);
 798}
 799
 800void __exit msm_dsi_phy_driver_unregister(void)
 801{
 802        platform_driver_unregister(&dsi_phy_platform_driver);
 803}
 804
 805int msm_dsi_phy_enable(struct msm_dsi_phy *phy,
 806                        struct msm_dsi_phy_clk_request *clk_req,
 807                        struct msm_dsi_phy_shared_timings *shared_timings)
 808{
 809        struct device *dev = &phy->pdev->dev;
 810        int ret;
 811
 812        if (!phy || !phy->cfg->ops.enable)
 813                return -EINVAL;
 814
 815        ret = dsi_phy_enable_resource(phy);
 816        if (ret) {
 817                DRM_DEV_ERROR(dev, "%s: resource enable failed, %d\n",
 818                        __func__, ret);
 819                goto res_en_fail;
 820        }
 821
 822        ret = dsi_phy_regulator_enable(phy);
 823        if (ret) {
 824                DRM_DEV_ERROR(dev, "%s: regulator enable failed, %d\n",
 825                        __func__, ret);
 826                goto reg_en_fail;
 827        }
 828
 829        ret = phy->cfg->ops.enable(phy, clk_req);
 830        if (ret) {
 831                DRM_DEV_ERROR(dev, "%s: phy enable failed, %d\n", __func__, ret);
 832                goto phy_en_fail;
 833        }
 834
 835        memcpy(shared_timings, &phy->timing.shared_timings,
 836               sizeof(*shared_timings));
 837
 838        /*
 839         * Resetting DSI PHY silently changes its PLL registers to reset status,
 840         * which will confuse clock driver and result in wrong output rate of
 841         * link clocks. Restore PLL status if its PLL is being used as clock
 842         * source.
 843         */
 844        if (phy->usecase != MSM_DSI_PHY_SLAVE) {
 845                ret = msm_dsi_phy_pll_restore_state(phy);
 846                if (ret) {
 847                        DRM_DEV_ERROR(dev, "%s: failed to restore phy state, %d\n",
 848                                __func__, ret);
 849                        goto pll_restor_fail;
 850                }
 851        }
 852
 853        return 0;
 854
 855pll_restor_fail:
 856        if (phy->cfg->ops.disable)
 857                phy->cfg->ops.disable(phy);
 858phy_en_fail:
 859        dsi_phy_regulator_disable(phy);
 860reg_en_fail:
 861        dsi_phy_disable_resource(phy);
 862res_en_fail:
 863        return ret;
 864}
 865
 866void msm_dsi_phy_disable(struct msm_dsi_phy *phy)
 867{
 868        if (!phy || !phy->cfg->ops.disable)
 869                return;
 870
 871        phy->cfg->ops.disable(phy);
 872
 873        dsi_phy_regulator_disable(phy);
 874        dsi_phy_disable_resource(phy);
 875}
 876
 877void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy,
 878                             enum msm_dsi_phy_usecase uc)
 879{
 880        if (phy)
 881                phy->usecase = uc;
 882}
 883
 884/* Returns true if we have to clear DSI_LANE_CTRL.HS_REQ_SEL_PHY */
 885bool msm_dsi_phy_set_continuous_clock(struct msm_dsi_phy *phy, bool enable)
 886{
 887        if (!phy || !phy->cfg->ops.set_continuous_clock)
 888                return false;
 889
 890        return phy->cfg->ops.set_continuous_clock(phy, enable);
 891}
 892
 893int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy,
 894        struct clk **byte_clk_provider, struct clk **pixel_clk_provider)
 895{
 896        if (byte_clk_provider)
 897                *byte_clk_provider = phy->provided_clocks->hws[DSI_BYTE_PLL_CLK]->clk;
 898        if (pixel_clk_provider)
 899                *pixel_clk_provider = phy->provided_clocks->hws[DSI_PIXEL_PLL_CLK]->clk;
 900
 901        return 0;
 902}
 903
 904void msm_dsi_phy_pll_save_state(struct msm_dsi_phy *phy)
 905{
 906        if (phy->cfg->ops.save_pll_state) {
 907                phy->cfg->ops.save_pll_state(phy);
 908                phy->state_saved = true;
 909        }
 910}
 911
 912int msm_dsi_phy_pll_restore_state(struct msm_dsi_phy *phy)
 913{
 914        int ret;
 915
 916        if (phy->cfg->ops.restore_pll_state && phy->state_saved) {
 917                ret = phy->cfg->ops.restore_pll_state(phy);
 918                if (ret)
 919                        return ret;
 920
 921                phy->state_saved = false;
 922        }
 923
 924        return 0;
 925}
 926
 927void msm_dsi_phy_snapshot(struct msm_disp_state *disp_state, struct msm_dsi_phy *phy)
 928{
 929        msm_disp_snapshot_add_block(disp_state,
 930                        phy->base_size, phy->base,
 931                        "dsi%d_phy", phy->id);
 932
 933        /* Do not try accessing PLL registers if it is switched off */
 934        if (phy->pll_on)
 935                msm_disp_snapshot_add_block(disp_state,
 936                        phy->pll_size, phy->pll_base,
 937                        "dsi%d_pll", phy->id);
 938
 939        if (phy->lane_base)
 940                msm_disp_snapshot_add_block(disp_state,
 941                        phy->lane_size, phy->lane_base,
 942                        "dsi%d_lane", phy->id);
 943
 944        if (phy->reg_base)
 945                msm_disp_snapshot_add_block(disp_state,
 946                        phy->reg_size, phy->reg_base,
 947                        "dsi%d_reg", phy->id);
 948}
 949