linux/drivers/gpu/drm/panel/panel-sony-acx424akp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * MIPI-DSI Sony ACX424AKP panel driver. This is a 480x864
   4 * AMOLED panel with a command-only DSI interface.
   5 *
   6 * Copyright (C) Linaro Ltd. 2019
   7 * Author: Linus Walleij
   8 * Based on code and know-how from Marcus Lorentzon
   9 * Copyright (C) ST-Ericsson SA 2010
  10 */
  11#include <linux/backlight.h>
  12#include <linux/delay.h>
  13#include <linux/gpio/consumer.h>
  14#include <linux/module.h>
  15#include <linux/of.h>
  16#include <linux/regulator/consumer.h>
  17
  18#include <video/mipi_display.h>
  19
  20#include <drm/drm_mipi_dsi.h>
  21#include <drm/drm_modes.h>
  22#include <drm/drm_panel.h>
  23#include <drm/drm_print.h>
  24
  25#define ACX424_DCS_READ_ID1             0xDA
  26#define ACX424_DCS_READ_ID2             0xDB
  27#define ACX424_DCS_READ_ID3             0xDC
  28#define ACX424_DCS_SET_MDDI             0xAE
  29
  30/*
  31 * Sony seems to use vendor ID 0x81
  32 */
  33#define DISPLAY_SONY_ACX424AKP_ID1      0x811b
  34#define DISPLAY_SONY_ACX424AKP_ID2      0x811a
  35/*
  36 * The third ID looks like a bug, vendor IDs begin at 0x80
  37 * and panel 00 ... seems like default values.
  38 */
  39#define DISPLAY_SONY_ACX424AKP_ID3      0x8000
  40
  41struct acx424akp {
  42        struct drm_panel panel;
  43        struct device *dev;
  44        struct backlight_device *bl;
  45        struct regulator *supply;
  46        struct gpio_desc *reset_gpio;
  47        bool video_mode;
  48};
  49
  50static const struct drm_display_mode sony_acx424akp_vid_mode = {
  51        .clock = 27234,
  52        .hdisplay = 480,
  53        .hsync_start = 480 + 15,
  54        .hsync_end = 480 + 15 + 0,
  55        .htotal = 480 + 15 + 0 + 15,
  56        .vdisplay = 864,
  57        .vsync_start = 864 + 14,
  58        .vsync_end = 864 + 14 + 1,
  59        .vtotal = 864 + 14 + 1 + 11,
  60        .vrefresh = 60,
  61        .width_mm = 48,
  62        .height_mm = 84,
  63        .flags = DRM_MODE_FLAG_PVSYNC,
  64};
  65
  66/*
  67 * The timings are not very helpful as the display is used in
  68 * command mode using the maximum HS frequency.
  69 */
  70static const struct drm_display_mode sony_acx424akp_cmd_mode = {
  71        .clock = 35478,
  72        .hdisplay = 480,
  73        .hsync_start = 480 + 154,
  74        .hsync_end = 480 + 154 + 16,
  75        .htotal = 480 + 154 + 16 + 32,
  76        .vdisplay = 864,
  77        .vsync_start = 864 + 1,
  78        .vsync_end = 864 + 1 + 1,
  79        .vtotal = 864 + 1 + 1 + 1,
  80        /*
  81         * Some desired refresh rate, experiments at the maximum "pixel"
  82         * clock speed (HS clock 420 MHz) yields around 117Hz.
  83         */
  84        .vrefresh = 60,
  85        .width_mm = 48,
  86        .height_mm = 84,
  87};
  88
  89static inline struct acx424akp *panel_to_acx424akp(struct drm_panel *panel)
  90{
  91        return container_of(panel, struct acx424akp, panel);
  92}
  93
  94#define FOSC                    20 /* 20Mhz */
  95#define SCALE_FACTOR_NS_DIV_MHZ 1000
  96
  97static int acx424akp_set_brightness(struct backlight_device *bl)
  98{
  99        struct acx424akp *acx = bl_get_data(bl);
 100        struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
 101        int period_ns = 1023;
 102        int duty_ns = bl->props.brightness;
 103        u8 pwm_ratio;
 104        u8 pwm_div;
 105        u8 par;
 106        int ret;
 107
 108        /* Calculate the PWM duty cycle in n/256's */
 109        pwm_ratio = max(((duty_ns * 256) / period_ns) - 1, 1);
 110        pwm_div = max(1,
 111                      ((FOSC * period_ns) / 256) /
 112                      SCALE_FACTOR_NS_DIV_MHZ);
 113
 114        /* Set up PWM dutycycle ONE byte (differs from the standard) */
 115        DRM_DEV_DEBUG(acx->dev, "calculated duty cycle %02x\n", pwm_ratio);
 116        ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
 117                                 &pwm_ratio, 1);
 118        if (ret < 0) {
 119                DRM_DEV_ERROR(acx->dev,
 120                              "failed to set display PWM ratio (%d)\n",
 121                              ret);
 122                return ret;
 123        }
 124
 125        /*
 126         * Sequence to write PWMDIV:
 127         *      address         data
 128         *      0xF3            0xAA   CMD2 Unlock
 129         *      0x00            0x01   Enter CMD2 page 0
 130         *      0X7D            0x01   No reload MTP of CMD2 P1
 131         *      0x22            PWMDIV
 132         *      0x7F            0xAA   CMD2 page 1 lock
 133         */
 134        par = 0xaa;
 135        ret = mipi_dsi_dcs_write(dsi, 0xf3, &par, 1);
 136        if (ret < 0) {
 137                DRM_DEV_ERROR(acx->dev,
 138                              "failed to unlock CMD 2 (%d)\n",
 139                              ret);
 140                return ret;
 141        }
 142        par = 0x01;
 143        ret = mipi_dsi_dcs_write(dsi, 0x00, &par, 1);
 144        if (ret < 0) {
 145                DRM_DEV_ERROR(acx->dev,
 146                              "failed to enter page 1 (%d)\n",
 147                              ret);
 148                return ret;
 149        }
 150        par = 0x01;
 151        ret = mipi_dsi_dcs_write(dsi, 0x7d, &par, 1);
 152        if (ret < 0) {
 153                DRM_DEV_ERROR(acx->dev,
 154                              "failed to disable MTP reload (%d)\n",
 155                              ret);
 156                return ret;
 157        }
 158        ret = mipi_dsi_dcs_write(dsi, 0x22, &pwm_div, 1);
 159        if (ret < 0) {
 160                DRM_DEV_ERROR(acx->dev,
 161                              "failed to set PWM divisor (%d)\n",
 162                              ret);
 163                return ret;
 164        }
 165        par = 0xaa;
 166        ret = mipi_dsi_dcs_write(dsi, 0x7f, &par, 1);
 167        if (ret < 0) {
 168                DRM_DEV_ERROR(acx->dev,
 169                              "failed to lock CMD 2 (%d)\n",
 170                              ret);
 171                return ret;
 172        }
 173
 174        /* Enable backlight */
 175        par = 0x24;
 176        ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
 177                                 &par, 1);
 178        if (ret < 0) {
 179                DRM_DEV_ERROR(acx->dev,
 180                              "failed to enable display backlight (%d)\n",
 181                              ret);
 182                return ret;
 183        }
 184
 185        return 0;
 186}
 187
 188static const struct backlight_ops acx424akp_bl_ops = {
 189        .update_status = acx424akp_set_brightness,
 190};
 191
 192static int acx424akp_read_id(struct acx424akp *acx)
 193{
 194        struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
 195        u8 vendor, version, panel;
 196        u16 val;
 197        int ret;
 198
 199        ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID1, &vendor, 1);
 200        if (ret < 0) {
 201                DRM_DEV_ERROR(acx->dev, "could not vendor ID byte\n");
 202                return ret;
 203        }
 204        ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID2, &version, 1);
 205        if (ret < 0) {
 206                DRM_DEV_ERROR(acx->dev, "could not read device version byte\n");
 207                return ret;
 208        }
 209        ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID3, &panel, 1);
 210        if (ret < 0) {
 211                DRM_DEV_ERROR(acx->dev, "could not read panel ID byte\n");
 212                return ret;
 213        }
 214
 215        if (vendor == 0x00) {
 216                DRM_DEV_ERROR(acx->dev, "device vendor ID is zero\n");
 217                return -ENODEV;
 218        }
 219
 220        val = (vendor << 8) | panel;
 221        switch (val) {
 222        case DISPLAY_SONY_ACX424AKP_ID1:
 223        case DISPLAY_SONY_ACX424AKP_ID2:
 224        case DISPLAY_SONY_ACX424AKP_ID3:
 225                DRM_DEV_INFO(acx->dev,
 226                             "MTP vendor: %02x, version: %02x, panel: %02x\n",
 227                             vendor, version, panel);
 228                break;
 229        default:
 230                DRM_DEV_INFO(acx->dev,
 231                             "unknown vendor: %02x, version: %02x, panel: %02x\n",
 232                             vendor, version, panel);
 233                break;
 234        }
 235
 236        return 0;
 237}
 238
 239static int acx424akp_power_on(struct acx424akp *acx)
 240{
 241        int ret;
 242
 243        ret = regulator_enable(acx->supply);
 244        if (ret) {
 245                DRM_DEV_ERROR(acx->dev, "failed to enable supply (%d)\n", ret);
 246                return ret;
 247        }
 248
 249        /* Assert RESET */
 250        gpiod_set_value_cansleep(acx->reset_gpio, 1);
 251        udelay(20);
 252        /* De-assert RESET */
 253        gpiod_set_value_cansleep(acx->reset_gpio, 0);
 254        usleep_range(11000, 20000);
 255
 256        return 0;
 257}
 258
 259static void acx424akp_power_off(struct acx424akp *acx)
 260{
 261        /* Assert RESET */
 262        gpiod_set_value_cansleep(acx->reset_gpio, 1);
 263        usleep_range(11000, 20000);
 264
 265        regulator_disable(acx->supply);
 266}
 267
 268static int acx424akp_prepare(struct drm_panel *panel)
 269{
 270        struct acx424akp *acx = panel_to_acx424akp(panel);
 271        struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
 272        const u8 mddi = 3;
 273        int ret;
 274
 275        ret = acx424akp_power_on(acx);
 276        if (ret)
 277                return ret;
 278
 279        ret = acx424akp_read_id(acx);
 280        if (ret) {
 281                DRM_DEV_ERROR(acx->dev, "failed to read panel ID (%d)\n", ret);
 282                goto err_power_off;
 283        }
 284
 285        /* Enabe tearing mode: send TE (tearing effect) at VBLANK */
 286        ret = mipi_dsi_dcs_set_tear_on(dsi,
 287                                       MIPI_DSI_DCS_TEAR_MODE_VBLANK);
 288        if (ret) {
 289                DRM_DEV_ERROR(acx->dev, "failed to enable vblank TE (%d)\n",
 290                              ret);
 291                goto err_power_off;
 292        }
 293
 294        /*
 295         * Set MDDI
 296         *
 297         * This presumably deactivates the Qualcomm MDDI interface and
 298         * selects DSI, similar code is found in other drivers such as the
 299         * Sharp LS043T1LE01 which makes us suspect that this panel may be
 300         * using a Novatek NT35565 or similar display driver chip that shares
 301         * this command. Due to the lack of documentation we cannot know for
 302         * sure.
 303         */
 304        ret = mipi_dsi_dcs_write(dsi, ACX424_DCS_SET_MDDI,
 305                                 &mddi, sizeof(mddi));
 306        if (ret < 0) {
 307                DRM_DEV_ERROR(acx->dev, "failed to set MDDI (%d)\n", ret);
 308                goto err_power_off;
 309        }
 310
 311        /* Exit sleep mode */
 312        ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
 313        if (ret) {
 314                DRM_DEV_ERROR(acx->dev, "failed to exit sleep mode (%d)\n",
 315                              ret);
 316                goto err_power_off;
 317        }
 318        msleep(140);
 319
 320        ret = mipi_dsi_dcs_set_display_on(dsi);
 321        if (ret) {
 322                DRM_DEV_ERROR(acx->dev, "failed to turn display on (%d)\n",
 323                              ret);
 324                goto err_power_off;
 325        }
 326        if (acx->video_mode) {
 327                /* In video mode turn peripheral on */
 328                ret = mipi_dsi_turn_on_peripheral(dsi);
 329                if (ret) {
 330                        dev_err(acx->dev, "failed to turn on peripheral\n");
 331                        goto err_power_off;
 332                }
 333        }
 334
 335        acx->bl->props.power = FB_BLANK_NORMAL;
 336
 337        return 0;
 338
 339err_power_off:
 340        acx424akp_power_off(acx);
 341        return ret;
 342}
 343
 344static int acx424akp_unprepare(struct drm_panel *panel)
 345{
 346        struct acx424akp *acx = panel_to_acx424akp(panel);
 347        struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
 348        u8 par;
 349        int ret;
 350
 351        /* Disable backlight */
 352        par = 0x00;
 353        ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
 354                                 &par, 1);
 355        if (ret) {
 356                DRM_DEV_ERROR(acx->dev,
 357                              "failed to disable display backlight (%d)\n",
 358                              ret);
 359                return ret;
 360        }
 361
 362        ret = mipi_dsi_dcs_set_display_off(dsi);
 363        if (ret) {
 364                DRM_DEV_ERROR(acx->dev, "failed to turn display off (%d)\n",
 365                              ret);
 366                return ret;
 367        }
 368
 369        /* Enter sleep mode */
 370        ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
 371        if (ret) {
 372                DRM_DEV_ERROR(acx->dev, "failed to enter sleep mode (%d)\n",
 373                              ret);
 374                return ret;
 375        }
 376        msleep(85);
 377
 378        acx424akp_power_off(acx);
 379        acx->bl->props.power = FB_BLANK_POWERDOWN;
 380
 381        return 0;
 382}
 383
 384static int acx424akp_enable(struct drm_panel *panel)
 385{
 386        struct acx424akp *acx = panel_to_acx424akp(panel);
 387
 388        /*
 389         * The backlight is on as long as the display is on
 390         * so no use to call backlight_enable() here.
 391         */
 392        acx->bl->props.power = FB_BLANK_UNBLANK;
 393
 394        return 0;
 395}
 396
 397static int acx424akp_disable(struct drm_panel *panel)
 398{
 399        struct acx424akp *acx = panel_to_acx424akp(panel);
 400
 401        /*
 402         * The backlight is on as long as the display is on
 403         * so no use to call backlight_disable() here.
 404         */
 405        acx->bl->props.power = FB_BLANK_NORMAL;
 406
 407        return 0;
 408}
 409
 410static int acx424akp_get_modes(struct drm_panel *panel,
 411                               struct drm_connector *connector)
 412{
 413        struct acx424akp *acx = panel_to_acx424akp(panel);
 414        struct drm_display_mode *mode;
 415
 416        if (acx->video_mode)
 417                mode = drm_mode_duplicate(connector->dev,
 418                                          &sony_acx424akp_vid_mode);
 419        else
 420                mode = drm_mode_duplicate(connector->dev,
 421                                          &sony_acx424akp_cmd_mode);
 422        if (!mode) {
 423                DRM_ERROR("bad mode or failed to add mode\n");
 424                return -EINVAL;
 425        }
 426        drm_mode_set_name(mode);
 427        mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 428
 429        connector->display_info.width_mm = mode->width_mm;
 430        connector->display_info.height_mm = mode->height_mm;
 431
 432        drm_mode_probed_add(connector, mode);
 433
 434        return 1; /* Number of modes */
 435}
 436
 437static const struct drm_panel_funcs acx424akp_drm_funcs = {
 438        .disable = acx424akp_disable,
 439        .unprepare = acx424akp_unprepare,
 440        .prepare = acx424akp_prepare,
 441        .enable = acx424akp_enable,
 442        .get_modes = acx424akp_get_modes,
 443};
 444
 445static int acx424akp_probe(struct mipi_dsi_device *dsi)
 446{
 447        struct device *dev = &dsi->dev;
 448        struct acx424akp *acx;
 449        int ret;
 450
 451        acx = devm_kzalloc(dev, sizeof(struct acx424akp), GFP_KERNEL);
 452        if (!acx)
 453                return -ENOMEM;
 454        acx->video_mode = of_property_read_bool(dev->of_node,
 455                                                "enforce-video-mode");
 456
 457        mipi_dsi_set_drvdata(dsi, acx);
 458        acx->dev = dev;
 459
 460        dsi->lanes = 2;
 461        dsi->format = MIPI_DSI_FMT_RGB888;
 462        /*
 463         * FIXME: these come from the ST-Ericsson vendor driver for the
 464         * HREF520 and seems to reflect limitations in the PLLs on that
 465         * platform, if you have the datasheet, please cross-check the
 466         * actual max rates.
 467         */
 468        dsi->lp_rate = 19200000;
 469        dsi->hs_rate = 420160000;
 470
 471        if (acx->video_mode)
 472                /* Burst mode using event for sync */
 473                dsi->mode_flags =
 474                        MIPI_DSI_MODE_VIDEO |
 475                        MIPI_DSI_MODE_VIDEO_BURST;
 476        else
 477                dsi->mode_flags =
 478                        MIPI_DSI_CLOCK_NON_CONTINUOUS |
 479                        MIPI_DSI_MODE_EOT_PACKET;
 480
 481        acx->supply = devm_regulator_get(dev, "vddi");
 482        if (IS_ERR(acx->supply))
 483                return PTR_ERR(acx->supply);
 484
 485        /* This asserts RESET by default */
 486        acx->reset_gpio = devm_gpiod_get_optional(dev, "reset",
 487                                                  GPIOD_OUT_HIGH);
 488        if (IS_ERR(acx->reset_gpio)) {
 489                ret = PTR_ERR(acx->reset_gpio);
 490                if (ret != -EPROBE_DEFER)
 491                        DRM_DEV_ERROR(dev, "failed to request GPIO (%d)\n",
 492                                      ret);
 493                return ret;
 494        }
 495
 496        drm_panel_init(&acx->panel, dev, &acx424akp_drm_funcs,
 497                       DRM_MODE_CONNECTOR_DSI);
 498
 499        acx->bl = devm_backlight_device_register(dev, "acx424akp", dev, acx,
 500                                                 &acx424akp_bl_ops, NULL);
 501        if (IS_ERR(acx->bl)) {
 502                DRM_DEV_ERROR(dev, "failed to register backlight device\n");
 503                return PTR_ERR(acx->bl);
 504        }
 505        acx->bl->props.max_brightness = 1023;
 506        acx->bl->props.brightness = 512;
 507        acx->bl->props.power = FB_BLANK_POWERDOWN;
 508
 509        ret = drm_panel_add(&acx->panel);
 510        if (ret < 0)
 511                return ret;
 512
 513        ret = mipi_dsi_attach(dsi);
 514        if (ret < 0) {
 515                drm_panel_remove(&acx->panel);
 516                return ret;
 517        }
 518
 519        return 0;
 520}
 521
 522static int acx424akp_remove(struct mipi_dsi_device *dsi)
 523{
 524        struct acx424akp *acx = mipi_dsi_get_drvdata(dsi);
 525
 526        mipi_dsi_detach(dsi);
 527        drm_panel_remove(&acx->panel);
 528
 529        return 0;
 530}
 531
 532static const struct of_device_id acx424akp_of_match[] = {
 533        { .compatible = "sony,acx424akp" },
 534        { /* sentinel */ }
 535};
 536MODULE_DEVICE_TABLE(of, acx424akp_of_match);
 537
 538static struct mipi_dsi_driver acx424akp_driver = {
 539        .probe = acx424akp_probe,
 540        .remove = acx424akp_remove,
 541        .driver = {
 542                .name = "panel-sony-acx424akp",
 543                .of_match_table = acx424akp_of_match,
 544        },
 545};
 546module_mipi_dsi_driver(acx424akp_driver);
 547
 548MODULE_AUTHOR("Linus Wallei <linus.walleij@linaro.org>");
 549MODULE_DESCRIPTION("MIPI-DSI Sony acx424akp Panel Driver");
 550MODULE_LICENSE("GPL v2");
 551